在MVVM模式中,ViewModel可以与View进行通信吗?

7
在MVP模式中,Presenter具有View的接口,因此Presenter可以调用iview.DoSomething()。那么在MVVM模式中呢?
根据John Gossman的UML图http://blogs.msdn.com/johngossman/archive/2006/04/13/576163.aspx, ViewModel没有View的接口。所以,似乎ViewModel和View只能通过绑定进行通信。(或者使用附加属性、混合行为等)
你们觉得呢?

嗨Skaffman,谢谢。你编辑了什么? :) - Michael Sync
他添加了设计模式标签。通过点击“编辑”文本来检查编辑历史记录。 - stiank81
谢谢...太好了...我没有看到那个"已编辑"的文字...我只看到了"编辑|回滚|删除|标记"。无论如何,感谢您为我的帖子添加了一个标签... - Michael Sync
4个回答

10
我同意John Gossman的观点。 ViewModel与View之间只能通过绑定来“交流”。 实际上,ViewModel不应该关心View。 它只需通过属性提供数据,由View决定动态绑定到ViewModel中的哪些内容。 如果ViewModel想要告诉View某些信息,则应通过绑定来隐式完成。
一个小时前有类似的问题 - 这里

非常感谢。我也同意这一点。当我写这篇文章http://michaelsync.net/2010/02/03/rules-of-mvvm时,有些人说在ViewModel中拥有View的接口是可以的。我告诉他们这将成为MVP模式。当然,我们可以混合使用这些模式,但我认为在VM中拥有一个View接口会违反MVVM模式。谢谢你的回答。我真的很感激。 - Michael Sync
听起来你走在了正确的道路上。很高兴能够帮到你。我会查看你的博客文章的! :-) - stiank81
谢谢。如果您对这篇文章有任何意见或建议,请告诉我.. :) - Michael Sync
很棒的帖子 :-) 我喜欢的一件事是,我可以让模型类全部保持干净-不添加只是因为视图需要的东西。例如,我不必只是因为视图需要它而保持某些列表排序-这取决于ViewModel来处理。但你也已经涵盖了这一点,说模型可以是简单的DTO。 - stiank81
谢谢,Stain。大多数人都同意我在那篇文章中提到的有关MVVM的所有事实(除了一个)。唯一让人们不同意的是,有些人认为他们可以在ViewModel中拥有一个视图接口。 - Michael Sync

1
整个MVVM的目的是大大减少WPF表单或用户控件的代码后台类中的代码量。这个想法是,任何经典MVC/MVP中由视图处理的内容都可以通过使用数据绑定和/或命令的组合来转换到VM中。在我普遍使用MVVM的过程中,我成功地完全删除了我的表单/用户控件中的所有后台代码,并且VM对其控制的视图没有直接的了解。如果您有一个真正无法通过数据绑定或命令处理的情况,请详细说明您的初始问题,我(或这里的众多更加有才华的MVVM专家之一)将尝试为您指明正确的方向。

谢谢。问题是,您认为在ViewModel中拥有View的接口是否违反了MVVM模式?例如:IPersonView、PersonView和PersonViewModel...而PersonViewModel拥有IPersonView... - Michael Sync
抱歉错过了评论,并看到您已经接受了Stians的答案,但出于完整性考虑,这是我的回复。我认为它违反了MVVM模式(在我的理解中),正如现在提到的,使用通过公开属性进行数据绑定是更新视图的方法。不过还是很高兴你得到了答案 :) - Leom Burke
谢谢,伙计...实际上,你的帖子也回答了我的问题,但问题是我不能将多个帖子标记为已解决。由于MVVM模式没有标准规则和所有者/创建者,我们需要询问每个人是否都同意这一点.. :) 这就是为什么我在不同社区中提出关于MVVM的问题,并将总结的信息写在我的一个帖子中的原因。 - Michael Sync

1
通常情况下,它会通过INotifyPropertyChanged事件来实现,如果没有其他的方式的话。

抱歉,我没听懂你的意思。你是在说要在 VM 中拥有一个 View 的接口吗? - Michael Sync
1
假设你在谈论C#,INotifyPropertyChanged接口上公开的事件通常由View(通过数据绑定)监听。数据绑定并不是真正的魔法 - 它只是将处理程序连接到INotifyPropertyChanged和INotifyCollectionChanged上的事件。但是,我会说通常VM确实会与View交互,以通知它数据的更改。它有一个抽象视图的概念,而不是特定的实现 - 它的通信应该限于“这个变化了”,而不是“所以改变这个控件”。 - kyoryu
是的..所以,“这个改变”限制=数据绑定,对吧? :) - Michael Sync
是的 :) 但是我实际上并没有看到其他类型通信存在问题,只要它基本上是发送数据,并且没有视图泄漏的知识。其他人可能比我更纯粹 :) - kyoryu

1
一个ViewModel能在MVVM模式中与View交流吗?
可以,但需要以一种解耦的方式。可以引入一个名为IView的接口来进行通信。
MVVM模式的目的是将逻辑从View中移动到ViewModel中。这样我们就能够对这个逻辑进行单元测试。

我很久以前看过WAF。我看到WAF的创建者在演示中在代码后面设置了密码。不确定他为什么这样做。
是的,但是以一种解耦的方式。
那么,MVP和MVVM模式之间有什么区别呢? 我们也可以将逻辑移动到MVP中的Presenter中。您认为从ViewModel设置iview.DoSomething是否可以接受?
- Michael Sync
从解耦和可测试性的角度来看,从ViewModel调用IView.DoSomething是被允许的。如果您使用绑定(Binding)代替,则需要定义ViewModel的属性。因此,View会知道ViewModel的属性。只是绑定使用了反射(不符合类型安全),但耦合度是相同的。 - jbe
为了实现解耦和可测试性,我们甚至不需要使用MVVM模式。MVC或MVP等模式也是可测试的。我仍然有两个问题。1)如果您说在ViewModel中拥有View的接口是可以的,那么您能告诉我MVP或MVVM之间的区别吗?您也可以阅读我与Glenn在此链接http://groups.google.com/group/wpf-disciples/browse_thread/thread/7588c66f21fb82af的讨论。2)您认为在View中执行((ViewModel)this.DataContext).DoThat()是否可以吗? - Michael Sync
  1. 对我来说,MVVM与PresentationModel模式(http://martinfowler.com/eaaDev/PresentationModel.html)是相同的,这也是Microsoft p&p团队的观点(http://msdn.microsoft.com/en-us/library/cc707885.aspx)。
  2. 是的,我认为这样做没问题:((ViewModel)this.DataContext).DoThat()。视图允许了解其关联的ViewModel。
- jbe
这就是关键。很多人认为MVVM是指代码后台文件中没有任何代码。这对于设计师/开发者的工作流程可能有优势。然而,如果你只关心耦合性和可测试性,那么“var name = ((ViewModel)this.DataContext.Name”与“{Binding Path=Name}”是相同的。绑定还从DataContext检索Name属性 - 为什么会有所不同呢? - jbe
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接