【问题标题】:Xamarin MVVM Pass Data to other ViewModels and shared ViewModelXamarin MVVM 将数据传递给其他 ViewModel 和共享 ViewModel
【发布时间】:2020-01-13 22:50:03
【问题描述】:

我有 2 个问题。

First=> 如何在 2 个 ViewModel 之间传递值?

例如,我正在添加数据并将其显示到 MainPAGE 中,同时我也想在 ChildPAGE 中显示相同的数据(Observable Collection)。在 ChildPAGE Xaml 中,我将 BindingContext 分配给 ViewModel,并将 listview 的数据源分配给该 Observable Collection。但我无法使其工作。我尝试了一些示例,但无法使其正常工作。如果在 ChildPAGE 的构造函数中加载数据,则它可以正常工作,否则将不起作用。我想,我会使用一个 ObservableCollection 来提高性能,但我认为,MVVM 中的机制是不同的。 那么如何在 2 页中使用一个 ObservableCollection。

Second => 如何在不使用构造函数的情况下在 ViewModel 之间传递数据。 示例:我有 2 个页面(MainPage 和 ChidPage)和 2 个 ViewModel(MainVM 和 ChildVM)。

Situation => 如果我将数据从 MainPage 传递到 ChildPage ,我会在构造函数中发送数据。但我想从 Childpage 获取数据到 MainPage 。所以 PopAsync 没有构造函数。我也尝试过 EventHandler 但它不起作用。

唯一的解决方案是消息中心吗?或者你对更好的表现有什么建议? MessagingCenter 是否还会因为 RAM 的高使用率而降低性能? 注意:(我想学习mvvm架构,所以不想用其他的MVVM框架,想全面了解MVVM和C#的概念。) 提前致谢

【问题讨论】:

  • 通常,await navService.PushAsync(new MyPage2(dataToShare)); 用于在页面/底层 VM 之间传递数据。在您的情况下,我将使用本地存储来缓存数据并将其加载到子/主页中。每次更新或删除时,缓存都会刷新。
  • 如果您真的非常喜欢高性能关键应用程序,那么请远离 Xamarin 并使用 C++,否则这些问题是合理的,但也无关紧要。在一天结束时,Xamarin 的植入可能会发生变化,有些事情将来可能会更快,而有些可能会更慢。
  • 帮自己一个忙,看看 Prism for Xamarin Forms。这将使您快速入门:xamgirl.com/prism-in-xamarin-forms-step-by-step-part-1
  • @除了messagecenter,可以看看FreshMvvm,MessageCenter确实会降低性能:betterask.erni/news-room/…

标签: xamarin mvvm


【解决方案1】:

您可以创建两个视图模型都依赖的模型类。模型本身将保存可观察集合,而视图模型引用可观察集合。这是在应用程序的整个生命周期中跨各种视图模型共享数据的好方法。通常您会希望使模型成为单例,以确保它确实是相同的数据。

如果您不想使用消息中心,可以使用具有其他好处的 MVVM 框架。我使用 Prism 来简化导航,您可以传递导航参数。

最后,这通常不是最好的选择,您可以在 App 对象中维护数据。您可以在 Properties 集合中设置值。这对于复杂的对象是不可取的。

编辑 首先,您将拥有一些 ObservableCollection 将包含的数据传输对象,除非您只是持有整数或其他东西。

public class MyDTO
{
  //fields for Data Transfer Object  
}

DTO 经常在您的模型中,但有时您需要一个复合类来保存 DTO 和 DTO 的集合

这是一个包含 ObservableCollection 的简单模型

public class MyCollectionModel
{
    #region Singleton Pattern
    private MyCollectionModel()
    {
    }
    public static MyCollectionModel Instance { get; } = new MyCollectionModel();
    #endregion
    private ObservableCollection<MyDTO> _dtos;
    public ObservableCollection<MyDTO> MyObservableCollection
    {
        get { return _dtos; }
        set { _dtos = value; }
    }
}

请注意,这实现了单例模式。它甚至可以实现 INotifyPropertyChanged。

接下来,您的视图模型(假设 MyVM1 和 MyVM2)将使用类似这样的方式引用您的模型中的 ObservableCollection。

    public class MyVM1 : INotifyPropertyChanged // Do the same with MyVM2, which would be the binding context for view 2
    {
        private MyCollectionModel _model;
        public MyVM1 ()
        {
            _model = MyCollectionModel.Instance;
        }
        private ObservableCollection<MyDTO> myVar;
        public ObservableCollection<MyDTO> MyProperty //Bind to this in your View1
        {
            get 
            { 
                return _model.MyObservableCollection; 
            }
            set
            {
                myVar = value;
                NotifyPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

我在这里留下了很多东西,并且真的没有时间构建整个项目来进行测试。我希望这会有所帮助。

【讨论】:

  • 感谢您的帮助先生。如果你有时间,如果可能的话,你能举个小例子吗?我也计划使用棱镜。但首先,我想了解主要思想。
  • 我在 EDIT 下添加了一个很有帮助的示例。这是一个非 Prism 示例。
  • 谢谢先生。效果很好。我添加了 MyCollectionModel() 的构造函数,它返回 null 所以我添加了这个 private MyCollectionModel() { MyObservableCollection = new ObservableCollection();如果你愿意,你可以编辑代码。谢谢
  • 顺便说一下,observable 集合效果很好,但字符串或整数不起作用。我尝试了很多东西,但我无法成功。
【解决方案2】:
  1. 您通常使用await navService.PushAsync(new MyPage2(dataToShare)); 在页面/VM 之间传递数据。这涉及使用构造函数。这是一个简单的例子:https://stackoverflow.com/a/47873920/1508398

  2. 由于您不想使用构造函数,您可以从您的服务加载子页面上的数据。或者,您可以将数据缓存在本地存储(客户端)上,然后简单地从那里加载到您的子页面/主页中。

【讨论】:

  • 我无法通过 navigation.popasync 传递数据
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-20
  • 2020-11-17
  • 2018-09-04
  • 1970-01-01
  • 2018-02-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多