.NET MAUI:如何从任何内容页面(MVVM)中读取/写入(获取/设置)一个全局对象

发布于 2025-02-14 01:28:26 字数 1874 浏览 2 评论 0 原文

我敢肯定,我在这里缺少一些深层或明显的概念:)

所以我现在有一个页面可以设置各种蓝牙传感器,并从心率监视器,速度表和节奏传感器中获取数据。 (使用plugin.ble)

因此,我在ViewModel中为一个称为bluetoothpage的内容page做所有这些。

我想在称为displaypage的其他内容page中显示我收到的数据。

我创建了一个可以保存我想要的数据的简单类(模型):

namespace TSDZ2Monitor.Models;

public partial class BluetoothData : ObservableObject
{
  //Heart rate raw data
  public int HRM { get; set; }
  public double HRR { get; set; }

  //SPD raw data
  public int SPDWheelRevolutions { get; set; }
  public double SPDWheelEventTime { get; set; }

  //CAD raw data
  public int CADCrankRevolutions { get; set; }
  public double CADCrankEventTime { get; set; }

}

那么,如何将数据从蓝牙页面获取到显示页面?

我怀疑我需要根据我的模型使用对象,并在蓝牙ViewModel(Easy ... ish)中使用数据填充它?

但是,我的显示页面如何看到此数据发生?

当我尝试使用反应性的事情时,这种事情是一场噩梦(状态!)

,或者我在这里有点简单:大声笑

解决方法:我可以按照 https://learn.microsoft.com/en-us/learn/learn/dotnet-maui/store-local-data/2-compare-storage-options - 是一种进入这样做还是可以使用对象完成?

G.

编辑:我认为我也可以使用MessagingService https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/messagingcenterals/messagingcenter and https://codemilltech.com/messing-with-xamarin-forms-messaging-center/ 如果我能弄清楚如何在MVVM上下文中使用它们。

另外使用MessagingCenter有什么区别和标准.NET活动处理程序,以告知感兴趣的各方更改吗?

I'm sure that I'm missing some deep or obvious concept here :)

So I have a page now that can setup various Bluetooth sensors and get data from a heart rate monitor, speedometer and cadence sensor. (Using Plugin.BLE)

So I do all of that in a ViewModel for a ContentPage called BluetoothPage.

I want to display the data I get in a different ContentPage called DisplayPage.

I have created a simple class (model) that can hold the data I want:

namespace TSDZ2Monitor.Models;

public partial class BluetoothData : ObservableObject
{
  //Heart rate raw data
  public int HRM { get; set; }
  public double HRR { get; set; }

  //SPD raw data
  public int SPDWheelRevolutions { get; set; }
  public double SPDWheelEventTime { get; set; }

  //CAD raw data
  public int CADCrankRevolutions { get; set; }
  public double CADCrankEventTime { get; set; }

}

So, how do I get the data from my Bluetooth page to my Display page?

I suspect I need to use an object based on my model and populate it with data in my Bluetooth viewmodel (easy...ish)?

But how can my Display page see this data as it happens?

When I tried working with ReactNative this sort of thing was a nightmare (State!)

Or am I being a bit simple in the head here :lol

Workaround: I could save the data to some local storage or sqlite as per https://learn.microsoft.com/en-us/learn/dotnet-maui/store-local-data/2-compare-storage-options - is that the way to do it, or can it be done with the object?

G.

Edit: I think I could also use the MessagingService https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/messagingcenter and https://codemilltech.com/messing-with-xamarin-forms-messaging-center/ if I can figure out how to use them in MVVM context.

Also What is the difference between using MessagingCenter and standard .NET event handlers for informing interested parties of changes?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

可是我不能没有你 2025-02-21 01:28:26

因此,使用消息中心似乎是一种方法。

遵循

我创建了一个消息标记类别:

namespace TSDZ2Monitor.Classes;

public class MessagingMarker
{
}

仅此而已。

在我想从中发送对象的ViewModel中,我做了

MessagingCenter.Send(new MessagingMarker(), "BTDataUpdate", btd);

btd是我创建的用于保存数据的类的实例:这是一个简化的模型:

namespace TSDZ2Monitor.Models;

public partial class BluetoothData : ObservableObject
{
  //Heart rate raw data
  private int hRM;
  public int HRM  //heart rate
  {
    get => hRM;
    set => SetProperty(ref hRM, value);
  }
  private double hRR; //heartrate R-R value
  public double HRR
  {
    get => hRR;
    set => SetProperty(ref hRR, value);
  }

  private double wheelRPM;
  public double WheelRPM
  {
    get => wheelRPM;
    set => SetProperty(ref wheelRPM, value);
  }

  private double cadence;
  public double Cadence
  {
    get => cadence;
    set => SetProperty(ref cadence, value);
  }

}

在发送页面的ViewModel的构造函数中?)

 public BluetoothData btd = new();

的XAML中不使用此视图模型,

这在我的接收视图模型中

我还创建了蓝牙类别的实例,但这用于XAML绑定

  [ObservableProperty]
  private BluetoothData bTData;

和构造函数中在ViewModel中,我

    BTData = new BluetoothData();

    MessagingCenter.Subscribe<MessagingMarker, BluetoothData>(this, "BTDataUpdate", (sender, arg) =>
    {
      //Debug.WriteLine($"Message received {arg}");
      BTData.HRM                   = arg.HRM;
      BTData.HRR                   = arg.HRR;
      BTData.WheelRPM              = arg.WheelRPM;
      BTData.Cadence               = arg.Cadence;
    });

效果很好,不知道对性能的影响可能是什么,但似乎反应迅速。

虽然我的思考方式是一个更具想法的解决方案,就是创建任何视图模型都可以访问的任何类的全局实例。

So it seems that using the MessagingCenter was a way to go.

Following the guidance in https://codemilltech.com/messing-with-xamarin-forms-messaging-center/

I created a MessagingMarker class:

namespace TSDZ2Monitor.Classes;

public class MessagingMarker
{
}

That's all.

In the ViewModel where I wanted to send an object from, I did

MessagingCenter.Send(new MessagingMarker(), "BTDataUpdate", btd);

where btd was an instance of a class I created to hold my data: Here is a simplified model:

namespace TSDZ2Monitor.Models;

public partial class BluetoothData : ObservableObject
{
  //Heart rate raw data
  private int hRM;
  public int HRM  //heart rate
  {
    get => hRM;
    set => SetProperty(ref hRM, value);
  }
  private double hRR; //heartrate R-R value
  public double HRR
  {
    get => hRR;
    set => SetProperty(ref hRR, value);
  }

  private double wheelRPM;
  public double WheelRPM
  {
    get => wheelRPM;
    set => SetProperty(ref wheelRPM, value);
  }

  private double cadence;
  public double Cadence
  {
    get => cadence;
    set => SetProperty(ref cadence, value);
  }

}

In the constructor of the ViewModel for the sending page (probably best somewhere else?)

 public BluetoothData btd = new();

This is not used in the XAML for this ViewModel

In my receiving ViewModel

I also created an instance of the BluetoothData class, but this is used in the XAML bindings

  [ObservableProperty]
  private BluetoothData bTData;

and in the constructor of the ViewModel I had

    BTData = new BluetoothData();

    MessagingCenter.Subscribe<MessagingMarker, BluetoothData>(this, "BTDataUpdate", (sender, arg) =>
    {
      //Debug.WriteLine(
quot;Message received {arg}");
      BTData.HRM                   = arg.HRM;
      BTData.HRR                   = arg.HRR;
      BTData.WheelRPM              = arg.WheelRPM;
      BTData.Cadence               = arg.Cadence;
    });

Well it works, don't know what the impact on performance might be, but it seems pretty responsive.

To my way of thinking though a more idea solution is to create a global instance of any class that any ViewModel can access.

暮年慕年 2025-02-21 01:28:26

我还需要这样做 - 就我而言,参考 observableCollection&lt; state&gt;状态来自多个页面。将其作为另一个可能的解决方案共享:

我创建了一个使用 observableCollection 作为 static> static 成员的类,该成员首次使用:

public class Filter
{
    ...
    public static ObservableCollection<State> StateSelections { get; } = new();
    ...
    public Filter(DataService dataService) : base()
    {
        this.dataService = dataService;

        PopulateData();
    }

    public async Task PopulateData()
    {
        // Populate the available selections
        await LoadStates();
    }

    public async Task LoadStates()
    {
        if (StateSelections?.Count > 0)
            return;
        ...
    }
}

对于使用集合的每个页面,其VM具有对类的实例的引用:

public partial class ParkListVM : BaseVM
{
    ...
    public Filter Filter { get; set; }
    ...

    public void PopulateData()
    {
        if (ParkListVM.Filter is null)
            ParkListVM.Filter = new Filter(dataService);
        ...
    }
}

该页面对显示静态集合的引用:

<ContentPage
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:vm="clr-namespace:NationalParks.ViewModels"
    xmlns:model="clr-namespace:NationalParks.Models"
    x:DataType="vm:ParkListVM"
    x:Class="NationalParks.Views.ParkListPage"
    Title="{Binding Title}">
    <ContentPage.Resources>
        <model:Filter x:Key="Filter"/>
    </ContentPage.Resources>
    ...
    <CollectionView ItemsSource="{Binding Source={x:Static model:Filter.StateSelections}}"
                    SelectionMode="Multiple"
                    SelectedItems="{Binding SelectedStates}">
        <CollectionView.ItemTemplate>
            <DataTemplate x:DataType="model:State">
                <VerticalStackLayout>
                    <Label Style="{StaticResource LabelMedium}" Text="{Binding Name}" />
                </VerticalStackLayout>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
    ...
</ContentPage>

I had need to also do this -- in my case, reference an ObservableCollection<State> States from multiple pages. Sharing this as another possible solution:

I created a class with the ObservableCollection as a static member which is populated once upon first use:

public class Filter
{
    ...
    public static ObservableCollection<State> StateSelections { get; } = new();
    ...
    public Filter(DataService dataService) : base()
    {
        this.dataService = dataService;

        PopulateData();
    }

    public async Task PopulateData()
    {
        // Populate the available selections
        await LoadStates();
    }

    public async Task LoadStates()
    {
        if (StateSelections?.Count > 0)
            return;
        ...
    }
}

For each page that uses the collection, its VM has a reference to an instance of the class:

public partial class ParkListVM : BaseVM
{
    ...
    public Filter Filter { get; set; }
    ...

    public void PopulateData()
    {
        if (ParkListVM.Filter is null)
            ParkListVM.Filter = new Filter(dataService);
        ...
    }
}

And the page has a reference to the static collection for display:

<ContentPage
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:vm="clr-namespace:NationalParks.ViewModels"
    xmlns:model="clr-namespace:NationalParks.Models"
    x:DataType="vm:ParkListVM"
    x:Class="NationalParks.Views.ParkListPage"
    Title="{Binding Title}">
    <ContentPage.Resources>
        <model:Filter x:Key="Filter"/>
    </ContentPage.Resources>
    ...
    <CollectionView ItemsSource="{Binding Source={x:Static model:Filter.StateSelections}}"
                    SelectionMode="Multiple"
                    SelectedItems="{Binding SelectedStates}">
        <CollectionView.ItemTemplate>
            <DataTemplate x:DataType="model:State">
                <VerticalStackLayout>
                    <Label Style="{StaticResource LabelMedium}" Text="{Binding Name}" />
                </VerticalStackLayout>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
    ...
</ContentPage>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文