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

C# 我应该如何在ViewModels之间进行通信?,c#,wpf,mvvm,viewmodel,mvvm-light,C#,Wpf,Mvvm,Viewmodel,Mvvm Light,我使用MVVM Light并使用打包的messenger系统在视图模型之间进行通信,但是我遇到了一个进退两难的问题!基本上,当用户单击客户记录时,会打开相应的视图,并随之实例化CustomerServiceWModel。此时,CustomerViewModel需要来自上一个视图模型(ViewAllCustomerViewModel)的选定客户ID,以便可以获取视图绑定到的选定客户信息(仍在后续?)。因此,最初我的想法是将ViewAllCustomerViewModel(选择要查看的客户)消息中的

我使用MVVM Light并使用打包的messenger系统在视图模型之间进行通信,但是我遇到了一个进退两难的问题!基本上,当用户单击客户记录时,会打开相应的视图,并随之实例化CustomerServiceWModel。此时,CustomerViewModel需要来自上一个视图模型(ViewAllCustomerViewModel)的选定客户ID,以便可以获取视图绑定到的选定客户信息(仍在后续?)。因此,最初我的想法是将ViewAllCustomerViewModel(选择要查看的客户)消息中的ID发送到CustomerServiceWModel。。。但是,在加载视图(此时消息已经广播)之前,CustomServiceWModel不会被实例化为能够接收消息

那么,解决这个问题的最佳方式是什么?到目前为止,我已经考虑过CustomerServiceModel在实例化后向ViewAllCustomerViewModel发送请求(基本上说“我准备好接收消息”),然后ViewAllCustomerViewModel将ID发送回CustomerServiceModel。。。但这是解决这一问题的必要途径吗?我觉得有点难看

否则,我在想,有没有其他沟通方式可以解释我的问题?但是,这不是消息传递系统的全部要点吗。。。是否能够在视图模型之间进行通信?或者我可以强制视图模型在启动时实例化吗?如果是,这将如何影响ViewModelLocator


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

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

在XAML中,它可以是

<ListBox x:Name="customers" />
<CustomerView Customer="{Binding SelectedItem, ElementName=customers}" />


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

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

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

public ViewModel2(ISession session)
        {
            _session = session;           
        }
这样,当您在BDD(行为驱动开发)中测试应用程序时,您可以在不使用视图的情况下测试应用程序。胶水就是模型

如图所示,您应该能够在没有视图的情况下测试应用程序。

到目前为止,我已经考虑过CustomerViewModel向 ViewAllCustomerViewModel一旦被实例化(基本上 说“我已准备好接收信息”),然后 ViewAllCustomerViewModel将ID发送回 自定义服务模型

我会继续这个想法。与其他答案不同,它将视图、视图模型和模型分开,并且不知道其他答案。不要说其他答案是错误的,甚至是不好的,您的选项可以定义为一个或任意一个:个人偏好、团队惯例、替换组件/模块的长期MVVM目标,以及编码的复杂性/易用性

我上面引用的你的想法的一个副作用是,你可以在任何时候提出要求,因为你已经设置好了。因此,如果您很容易更改何时执行该请求,或者如果您需要请求更新,那么您将使用相同的通信体系结构


最后,我更喜欢它,因为如果您更改了模型、视图或视图模型,那么组件之间的信息通信的核心概念是相同的。

就我个人而言,我曾经使用MVVM Light Messenger,但我发现我有办法让许多消息四处传播,我不喜欢使用“神奇”Messenger的感觉。我所做的是对以下链接的回答


现在我警告你们,我回答了我自己的问题,并没有人将其视为好的或坏的实践,但它适用于我的情况,并且已经消除了对MVVM Light Messenger的需要。因为我的程序在实现中使用了多个线程,所以我将存储库中的所有条目更改为以CurrentThread.ManagedThreadId为键的字典。

我遇到了两个视图模型相互通信的相同情况。我已经使用MicrosoftPrism框架发布和订阅

在您的案例中,CustomerServiceWModel是父视图,ViewAllCustomerViewModel是子视图

  • 从下载prism框架“Microsoft.Practices.prism.PubSubEvents.dll”

  • 将prism引用添加到项目“Microsoft.Practices.prism.PubSubEvents.dll”

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

      class Notifications : PubSubEvent<string>
      {
    
      }
    
  • 转到Popover模型(ViewAllCustomersViwModel)按钮事件处理和下面的代码。现在它已经发布

  • ViewAllCustomersViwModel.cs
    中:

          public void OnSelectedItem(Item item)
         {
                SessionInfo.Instance.eventHanlder.GetEvent<Notification>().Publish(item.id);
    
          }
    
    selecteditem(项)上的公共无效
    {
    SessionInfo.Instance.EventHander.GetEvent().Publish(item.id);
    }
    
  • 必须在需要时订阅这些事件聚合器。因此,在父视图模型(CustomServiceWModel)上添加以下代码
  • CustomerViewModel.cs

           public class CustomerViewModel
          {
                   public CustomerViewModel()
                  {
                      SessionInfo.Instance.eventHanlder.GetEvent<Notifications>().Subscribe(OnReceivedNotification);
    
                   }
    
            //Handling the notification 
        public void OnReceivedNotification(string itemId)
            {
                Debug.WriteLine("Item Id is :" + itemId);
    
            }
    
    
         }
    
    public类CustomerViewModel
    {
    公共CustomerServiceModel()
    {
    SessionInfo.Instance.EventHander.GetEvent().Subscribe(OnReceivedNotification);
    }
    //处理通知
    收到通知时公共作废(字符串itemId)
    {
    Debug.WriteLine(“项目Id为:“+itemId”);
    }
    
           public class CustomerViewModel
          {
                   public CustomerViewModel()
                  {
                      SessionInfo.Instance.eventHanlder.GetEvent<Notifications>().Subscribe(OnReceivedNotification);
    
                   }
    
            //Handling the notification 
        public void OnReceivedNotification(string itemId)
            {
                Debug.WriteLine("Item Id is :" + itemId);
    
            }
    
    
         }