View是否可以订阅ViewModel CLR事件?

时间:2010-05-10 22:07:49

标签: silverlight mvvm mvvm-light

有时视图模型需要引发通知,视图应该处理并做出响应,特别是。当这些无法建模为属性和属性更改通知时。

MVVM Light中的任何内容都可以允许视图通过声明性Xaml标记来侦听事件并将视图模型通知转换为用户界面操作吗?

4 个答案:

答案 0 :(得分:3)

就个人而言,我发现了从VM中引发事件并在某些情况下可接受的视图中捕获它们的技术。我通常喜欢在这种情况下使用Messenger,特别是如果你需要自定义事件args(因为声明一个新的事件args类和一个新的委托是相当多的工作)。

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

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

我通常根据各种因素在Messenger和IDialogService之间移动。我最近倾向于支持基于接口的方法,因为它更容易测试(但是,对于YMMV来说,Messenger也是非常可测试的)。

干杯, 劳伦

答案 1 :(得分:2)

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

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

等等。

答案 2 :(得分:1)

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

  

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

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

答案 3 :(得分:1)

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);
}