我应该如何在ViewModels之间进行通信?

我正在使用MVVM Light并使用打包的信使系统在视图模型之间进行通信,但是我遇到了一些两难的问题! 基本上,当用户单击客户记录时,将打开相应的视图,并使用它来实例化CustomerViewModel 。 此时, CustomerViewModel需要来自先前视图模型( ViewAllCustomersViewModel )的所选客户ID,以便它可以获取视图所绑定的选定客户信息(仍然跟随?)。 所以最初我的想法也是将来自ViewAllCustomersViewModel (选择要查看的客户)的消息中的ID发送到CustomerViewModel …但是, CustomerViewModel未实例化为能够在加载视图之前接收消息(此时消息已经播出)!

那么,解决这个问题的最佳方法是什么? 到目前为止,我已经考虑过CustomerViewModel在实例化后向ViewAllCustomersViewModel发送请求(基本上说“我准备接收消息”),然后ViewAllCustomersViewModel将ID发送回CustomerViewModel ……但这是一个解决这个问题的必要方法? 这对我来说似乎有点难看!

否则,我在想是否有另一种沟通方式可以解释我遇到的问题? 但是,这不是消息系统的全部意义……能够在视图模型之间进行通信吗? 或者我可以强制视图模型在启动时实例化吗? 如果是这样,那将如何影响ViewModelLocator

我希望我已经清楚地概述了这个问题,为了解释的目的,我使用了虚构的视图模型名称…请随时编辑或建议您希望我添加的任何其他信息!

您是否尝试通过您的模型进行交流? 直到最后我才能阅读您的主题,但这是我在ViewModels之间进行通信的方式。 两个View Models都具有会话实例。

public ViewModel1(ISession session) { _session = session; } public ViewModel2(ISession session) { _session = session; } 

这样,当您在BDD(行为驱动开发)中测试应用程序时,您可以在没有视图的情况下测试应用程序。 胶水是模型。

正如您在此图片中看到的那样,您应该能够在没有视图的情况下测试您的应用程序。 在此处输入图像描述

我遇到了两种视图模型相互通信的情况。 我使用Microsoft PRISM框架来发布和订阅。

在您的情况下,CustomerViewModel是父View,ViewAllCustomersViewModel是子视图。

  1. 从https://www.nuget.org/packages/Prism.PubSubEvents/下载prism框架“Microsoft.Practices.Prism.PubSubEvents.dll”

  2. 为项目“Microsoft.Practices.Prism.PubSubEvents.dll”添加prism引用

  3. 创建一些用于通信调制解调器的自定义类。

      class Notifications : PubSubEvent { } 
  4. 为项目创建IEventAggregator eventAggregator单例实例并初始化它。

      public sealed class SessionInfo { public IEventAggregator eventHanlder; private SessionInfo (){ } private static SessionInfo _instance = null; public static SessionInfo Instance{ get{ lock (lockObj){ if (_instance == null) { _instance = new SessionInfo (); _instance.eventHanlder= new EventAggregator(); } } return _instance; } } } 
  5. 转到Popover模型(ViewAllCustomersViwModel)按钮事件处理及其下面的代码。现在它已经发布。

ViewAllCustomersViwModel.cs

  public void OnSelectedItem(Item item) { SessionInfo.Instance.eventHanlder.GetEvent().Publish(item.id); } 
  1. 这些事件聚合器必须在需要的地方进行订阅。 因此,在您的父视图模型(CustomerViewModel)上添加以下代码

CustomerViewModel.cs

  public class CustomerViewModel { public CustomerViewModel() { SessionInfo.Instance.eventHanlder.GetEvent().Subscribe(OnReceivedNotification); } //Handling the notification public void OnReceivedNotification(string itemId) { Debug.WriteLine("Item Id is :" + itemId); } } 

欲获得更多信息:

https://sites.google.com/site/greateindiaclub/mobil-apps/windows8/communicationbetweenviewmodelsinwindows8mvvmpattern

我相信标准的方法是通过View传递它。 根据您实例化视图的方式,可能是要在XAML,构造函数参数或其他任何内容中绑定的DependencyProperty。 然后View将它传递给它的ViewModel(将其推送到VM,而不是解决方法:ViewModel不应该知道View)。 这样您就可以得到一个独立的封闭组件(您的视图),而外部代码不知道它的内部实现(即ViewModel)。

在XAML中它可以是类似的东西

   

然后在CustomerPropertyChanged处理程序中将值推送到ViewModel。

就个人而言,我曾经使用MVVM-Light Messenger,但发现我有很多信息飞来飞去,我不喜欢使用“神奇”信使的感觉。 我所做的是概述为以下链接的答案

启动时将数据传递给新ViewModel的最佳方法 。

现在我警告你,我回答了我自己的问题,没有人把它作为好的或坏的做法,但它适用于我的情况并且已经消除了对MVVM-Light Messenger的需求。 因为我的程序在我的实现中使用多个线程,所以我将存储库中的所有条目更改为Dictionarys,并将CurrentThread.ManagedThreadId作为Key。

到目前为止,我已经考虑过CustomerViewModel在实例化后向ViewAllCustomersViewModel发送请求(基本上说“我准备接收消息”),然后ViewAllCustomersViewModel将ID发送回CustomerViewModel …

我会继续这个想法。 与其他答案不同,它使视图,视图模型和模型与其他视图保持独立和不知情。 不是说其他​​答案是错误的,甚至是坏的,您的选项可以定义为以下一个或任何一个:个人偏好,团队惯例,替换组件/模块的长期MVVM目标,以及编码的复杂性/易用性。

我上面引用的一个副作用,我更喜欢的是,你可以随时要求,因为你已经设置了它。 因此,如果您非常轻松地更改何时执行该请求,或者您需要请求更新 ,则可以使用相同的通信体系结构。

最后,我更喜欢它,因为如果您更改模型或视图或视图模型 – 您保持在组件之间传递信息的核心概念。