在MVVM模式中,View-first和ViewModel-first有什么优点和缺点?

我将介绍如何在真实世界的应用程序中使用MVVM,以及如何在您的应用程序中使用MVVM作为模式时涉及的宗教战争devise决策。 在MVVM应用程序中,有两种主要方式(我知道的)实例化一个新的View / ViewModel对:

  1. View-First在其中创build视图,并创build自己的ViewModel并将其设置为其DataContext。
  2. ViewModel-首先在其中创build新的视图模型并创build新的视图以响应ViewModel属性的更改,通常使用ItemsControls和/或DataTemplates。

根据你的经验,每种方法有哪些优缺点? 他们启用了什么,你遇到什么问题?

结果摘要


  • 首先查看 – 优点
    • 轻松跟踪ViewModel使用的ViewModel
  • 查看第一 – 缺点
    • 不允许使用多个ViewModel轻松使用单个视图
    • 需要额外的事件来处理Views和ViewModels之间的通信
  • ViewModel首先 – 优点
    • 允许更完整的逻辑testing来打开新的Views和ViewModels
    • 随着应用程序变得越来越大,趋于干燥
    • View和ViewModel更加独立,可以更容易地分开处理
  • ViewModel首先 – 缺点
    • 在没有DataTemplateSelector并键入DataTemplates的Silverlight中设置更加困难。

鉴于WPF中的数据模板function,我觉得ViewModel-First是WPF 打算使用的方式。

我将澄清一下声明:数据模板允许你永远不会从你的ViewModel实例化视图。 如果做得对,你的Views和ViewModels可以保存在不相互引用的独立项目中。 此外,ViewModel项目甚至不应该引用任何PresentationFramework程序集,使得您的ViewModel可由任何可以想象的用户使用。

我倾向于先select视图模型,因为我觉得它最好遵循DRY规则。 当你开始创build更大规模的应用程序时,我发现这使得testing更容易,因此超过了设置应用程序时需要处理的头痛问题。

警告 – 我使用WPF而不是Silverlight。

通过VM实例化V(这是我做的方式),视图是独立的,可以独立于VM使用(例如在devise器中)

就个人而言,我正在MVVMC(模型,视图,ViewModel,控制器),我有一个控制类,实例ViewModels和视图和“join他们”。 然后,C还处理获取数据(以及caching等)以及任何跨VM和Vs的通信(例如,如果V被实例化,将命令路由到其VM以执行一些动作,则VM可能会要求C执行代表其采取行动; C则可以提出其他虚拟机可以处理的适当事件

如果(无论是否使用控制器)我需要一个虚拟机与另一个虚拟机交谈,如果V实例化一个虚拟机是很难做到这一点的 – 因为我不需要暴露V中的虚拟机(或者至less使一些接口第二个虚拟机可以和第一个虚拟机进行通信)。

我们首先使用了ViewModel,但是当进行外包,混合使用成为最重要的事情时,我的老板说View-first比Viewmodel优先 – 我不同意他(但是一对多不是最好的比例);因为现在我们在后面的代码中有一些与视图事件有关的怪异连接。 现在我处于不归路了,因为变化,我陷入了一些自定义的控制。

我使用了View-first(sort-of)方法。 我使用testing数据的虚拟视图模型与我的客户端协作定义视图。 当我们满意时,我继续从“虚拟”中提取一个接口,并实现真正的ViewModel。 我发现这种方法最吸引人的原因如下:

  • 原型devise在时间上非常昂贵,而且我经常在第四次或第五次尝试中做对(ish)。
  • 当我有一个遵循的接口时,ViewModels往往很容易实现。

我在WPF中工作,但我认为SL中不会有太大的不同。 而且,我从不花费时间来testing可能属于我select的方法的视图。

我更喜欢使用视图模型的第一种方法。 出于很多原因:

  • Vms是包含大部分逻辑的应用程序,除了胶水代码之外,还包含行为或触发器的forms。
  • 如果您创build了视图,那么您需要对其生命和清理代码负责。 你必须处理线程和其他难以testing的问题。 另一方面,你创buildvms,并通过数据模板留下WPF的视图创build逻辑..你不必担心线程问题。 而且会有更好的问题分离。
  • 随着虚拟机首先接近零代码。
  • 通过对视图和vms进行项目级隔离,您可以限制开发人员在视图模型中使用视图特定的事物(如调度程序),从而留下更清洁和可testing的代码库。 即查看项目sprojec到VM。 而VM项目不应该参考任何演示文稿的lib。
  • 如果view和vm之间有明确的界限。 两者都可以进化并且不会脆弱。