【问题标题】:Is it possible for the View to subscribe ViewModel CLR event?View 是否可以订阅 ViewModel CLR 事件?
【发布时间】:2010-05-10 22:07:49
【问题描述】:

有时视图模型需要发出通知,视图应该处理并做一些响应,尤其是。当这些不能被建模为属性和属性更改通知时。

MVVM Light 中是否有任何东西可以让视图通过声明性 Xaml 标记侦听事件并将视图模型通知转换为用户界面操作?

【问题讨论】:

  • 你是什么意思?虚拟机应该拥有视图自身呈现所需的所有信息,不需要虚拟机和视图之间的通信通道。
  • 您是在谈论处理弹出窗口和导航吗?

标签: silverlight mvvm mvvm-light


【解决方案1】:

我个人认为在某些情况下可以接受从 VM 引发事件并在视图中捕获它们的技术。不过,我通常更喜欢在这种情况下使用 Messenger,尤其是当您需要自定义事件参数时(因为声明一个新的事件参数类和一个新的委托需要做很多工作)。

此外,事件处理程序是视图和视图模型之间的紧密耦合,而您通常更喜欢松耦合,但如果您知道这一事实和后果,那么为什么不...

另一种技术(例如导航、对话框等)是使用您需要的方法声明接口(例如 IDialogService 与 AskConfirmation 和 ShowMessage 方法)。然后让一个类实现该接口(可以是 MainWindow/MainPage 本身)并将其传递给 ViewModel(例如在调用 InitializeComponent 之后的 View 的构造函数中)。在 VM 中,在需要时调用这些方法。这具有非常容易测试的优点(只需模拟 IDialogService 并检查方法是否被调用)。

我通常会根据各种因素在 Messenger 和 IDialogService 之间切换。不过,我最近倾向于使用基于接口的方法,因为它更容易测试(但 Messenger 也很容易测试,所以 YMMV)。

干杯, 洛朗

【讨论】:

    【解决方案2】:

    在“纯”MVVM 解决方案中,唯一应该将 View 连接到 ViewModel 的是绑定。没有什么可以阻止您将 DataContext 转换为 ViewModel 类型并在视图中挂钩事件,但这有点违背了使用 MVVM 方法的目的。作为替代方案,请尝试重新考虑为什么您认为需要向视图引发事件:

    • 需要显示弹出窗口吗?当视图模型将通知对象“插入”到绑定集合中时,可以使用各种“弹出通知”绑定列表以及适当的模板在视图上创建弹出窗口。
    • 需要强制打开下拉菜单或一些类似的 UI 操作?将 UI 上的相应属性绑定到视图模型属性,将模式设置为双向,并在视图模型上根据需要进行设置。

    等等等等

    【讨论】:

      【解决方案3】:

      你是对的,有时 ViewModel 需要与 View 通信。一种方法是 ViewModel 引发 View 侦听的 CLR 事件。这可以在 View 的代码隐藏中完成。

      MVVM 并不是要消除视图的代码隐藏!这是关于关注点分离和通过单元测试提高可测试性。

      实现 ViewModel 和 View 之间通信的另一种方法是引入接口 (IView)。有关此方法的更多信息,请访问 WPF Application Framework (WAF) 项目网站。

      【讨论】:

        【解决方案4】:

        在 MVVMLight 中确实有一种支持的技术来处理从 ViewModel 向 View 发送消息。查看 GalaSoft.MvvmLight.Messaging 命名空间内部。除了下面的示例之外,还有一种更好的方式来发送拨号消息,但这只是一个简单的示例。

        例子

        视图模型

        public MainPageViewModel()
        {
            Messenger.Default.Send("Payment");
        }
        

        查看

        public MainPage()
        {
            Messenger.Default.Register<string>(this, DialogRequested);
        }
        
        private DialogRequested(string message)
        {
            MessageBox.Show(message);
        }
        

        【讨论】:

          猜你喜欢
          • 2013-09-05
          • 1970-01-01
          • 2013-03-06
          • 1970-01-01
          • 1970-01-01
          • 2017-02-18
          • 1970-01-01
          • 2011-08-14
          • 1970-01-01
          相关资源
          最近更新 更多