7

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

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

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

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

4

5 回答 5

5

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

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

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

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

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

于 2013-09-26T14:30:27.633 回答
4

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

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

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

  2. 将棱镜引用添加到您的项目“Microsoft.Practices.Prism.PubSubEvents.dll”

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

      class Notifications : PubSubEvent<string>
      {
    
      }
    
  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. 转到弹出框模型(ViewAllCustomersViwModel)按钮事件处理和下面的代码。现在它已经发布了。

ViewAllCustomersViwModel.cs

      public void OnSelectedItem(Item item)
     {
            SessionInfo.Instance.eventHanlder.GetEvent<Notification>().Publish(item.id);

      }
  1. 这些事件聚合器必须在需要的地方订阅。因此,在您的父视图模型 (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);

        }


     }

了解更多信息:

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

于 2014-09-12T13:36:09.023 回答
2

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

在 XAML 中,它可能类似于

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

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

于 2013-09-26T14:27:28.360 回答
2

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

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

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

于 2013-09-26T15:58:30.367 回答
1

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

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

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

最后,我更喜欢它,因为如果您更改模型或视图或视图模型 - 您将保持组件之间通信信息的相同核心概念。

于 2013-09-26T15:41:48.463 回答