MVVM的基本概念 – ViewModel应该做什么?

试图掌握MVVM的概念,我已经阅读了几个博客,并看了几个项目。

据我所知,一个视图是愚蠢的,它只是知道如何呈现一些传递给它的东西。

模型只是简单的数据,而ViewModel就像是两者之间的填充,它应该从模型中获取信息并将其传递给View ,而View应该知道如何呈现它。 或者相反,如果View中的信息发生变化,它应该将更改传递给Model

但我仍然不知道如何应用这个概念。 有人能解释一个非常简单的情况,所以我可以把握这个概念吗? 我已经看了好几个项目,但还是没有完全意义,所以如果有人能用简单的英文写出来,那会很好。

谢谢 :)

我喜欢这样想:

正如你所说,意见是愚蠢的。 MSDN关于MVVM的开创性和经常链接的作者Josh Smith曾表示,观点是“数据所穿的衣服”。 视图从不实际包含数据或直接操纵它,它们只是绑定到视图模型的属性和命令。

模型是对应用程序域进行build模对象,如业务对象。 你的应用程序是一个音乐商店? 也许你的模型对象将是艺术家,专辑和歌曲。 你的应用程序是一个组织图表浏览器吗? 也许你的模型对象将是经理和员工。 这些模型对象与任何types的视觉渲染都没有关系,甚至与你将它们放入的应用程序没有直接的关系 – 你的模型对象应该完全独立地作为代表某种types的对象族的域。 模型层通常还包括诸如服务访问器之类的东西。

这将我们带入Viewmodels。 他们是什么? 它们是模拟GUI应用程序的对象,意味着它们提供了视图所使用的数据和function。 它们定义了您正在构build的实际应用程序的结构和行为。 对于模型对象,域是您select的任何域(音乐商店,组织图表浏览器等),但对于视图模型,域是graphics应用程序。 你的视图模型将封装应用程序所做的一切行为和数据。 他们将公开对象和列表作为属性,以及诸如命令之类的东西。 一个命令只是一个行为(在其最简单的方法调用中)包装到一个对象中,这个想法是非常重要的,因为视图是由数据绑定驱动的,而数据绑定则将视觉控件附加到对象上。 在MVVM中,您不会给button一个Click处理方法,而是将其绑定到一个命令对象(由viewmodel中的一个属性提供),该对象包含您单击时要运行的function。

对我来说,最容易混淆的是:

  • 尽pipe视图模型是graphics应用程序的模型,但它们并不直接引用或使用视觉概念。 例如,您不希望在ViewModel中引用Windows控件 – 这些事情都在视图中进行。 ViewModels只是暴露数据和行为控制或其他对象将绑定到他们。 例如 – 你有一个ListBox的观点吗? 你的viewmodel几乎肯定会有一些collections。 你的观点是否有button? 你的viewmodel几乎肯定会有一些命令。
  • 有几种对象可以被视为“视图模型”。 要理解的最简单的视图模型是直接表示1:1关系的控件或屏幕,如“屏幕XYZ有一个文本框,一个列表框和三个button,所以viewmodel需要一个string,一个集合,和三个命令“。 另一种适合视图模型层的对象是一个模型对象的包装,使其具有行为特征,使得视图更易于使用 – 这就是您进入“厚”和“薄”视图模型层概念的地方。 “瘦”视图模型层是一组视图模型,将模型对象直接展示给视图,意味着视图最终直接绑定到模型对象上的属性。 这可以适用于简单的只读视图,但是如果你想要有与每个对象相关的行为呢? 您不希望在模型中使用该模型,因为该模型与应用程序无关,只与您的域有关。 你可以把它放在一个包装你的模型对象的对象中,并提供更多的绑定友好的数据和行为。 这个包装器对象也被认为是一个视图模型,并让它们产生一个“较厚”的视图模型层,其视图永远不会直接绑定到模型类上的任何东西。 集合将包含包装模型的视图模型,而不仅仅包含模型本身。

兔子的洞越来越深 – 有很多成语可以像ValueConverters一样让MVVM发挥作用,当你开始思考如Blendability,testing,以及如何在你的应用中传递数据,并且确保每个视图模型都可以访问它所需要的行为(这是dependency injection的地方),但是希望上面是一个好的开始。 关键是要把你的视觉效果,你的领域,实际应用的结构和行为视为三个不同的东西。

我已经用MVVM上的这个系列来描述这个 “纯英文”了。 特别是, 这个图可能是最简单,最简单的解释。

这就是说,基本上,“模型”是你的数据或业务规则。 它真的不应该知道如何或将在哪里使用,特别是不会使用哪种技术。 “模型”是应用程序的核心内容 – 它不应该担心应用程序是否是WPF,Silverlight,Windows Forms,ASP.NET等 – 它只是纯粹的“本身”。

“视图”是完全技术特定的部分。 在MVVM中,理想情况下,视图应该是几乎100%的XAML,因为这提供了一些巨大的灵活性收益。

但是,需要将模型中的信息转化为可用于手边技术的某种forms,这就是ViewModel发挥作用的地方。 例如,这通常会将模型类“包装”到包含Commands(用于运行逻辑)的特定数据的“ViewModel”中,实现INotifyPropertyChanged (用于数据绑定支持)等。就是这样 – 这是使得View可用的模型。

使用这个非常有用的文章作为来源,下面是ViewViewModelModel的总结。


视图:

  • 该视图是一个可视元素,如窗口,页面,用户控件或数据模板。 该视图定义视图中包含的控件及其视觉布局和样式。

  • 该视图通过其DataContext属性引用视图模型。 视图中的控件是绑定到视图模型公开的属性和命令的数据。

  • 该视图可以定制视图和视图模型之间的数据绑定行为。 例如,视图可以使用值转换器来格式化要显示在UI中的数据,或者可以使用validation规则来向用户提供额外的input数据validation。

  • 该视图定义并处理UI视觉行为,例如可能从视图模型中的状态改变或者通过用户与UI的交互而触发的animation或转换。

  • 视图的代码隐藏可以定义UI逻辑来实现难以在XAML中expression的视觉行为,或者需要直接引用视图中定义的特定UI控件。

注意:
因为视图模型应该没有对视图中特定的视觉元素的明确的知识,编程操作视图中的视觉元素的代码应该驻留在视图的代码隐藏中或者封装在行为中。


查看模型:

  • 视图模型是一个非可视类,并不是从任何WPF或Silverlight基类派生。 它封装了在应用程序中支持用例或用户任务所需的表示逻辑。 视图模型可独立于视图和模型进行testing。

  • 视图模型通常不直接引用视图。 它实现了视图可以绑定数据的属性和命令。 它通过INotifyPropertyChangedINotifyCollectionChanged接口通过更改通知事件通知任何状态更改的视图。

  • 视图模型协调视图与模型的交互。 它可以转换或操作数据,以便视图可以轻松使用数据,并可以实现模型中可能不存在的其他属性。 它也可以通过IDataErrorInfoINotifyDataErrorInfo接口实现数据validation。

  • 视图模型可以定义视图可以向用户可视地表示的逻辑状态。

注意:
任何对应用程序的逻辑行为都很重要的东西都应该进入视图模型。 检索或操作通过数据绑定显示在视图中的数据项的代码应驻留在视图模型中。


模型:

  • 模型类是封装应用程序的数据和业务逻辑的非可视类。 他们负责pipe理应用程序的数据,并通过封装所需的业务规则和数据validation逻辑来​​确保其一致性和有效性。

  • 模型类不直接引用视图或视图模型类,也不依赖于它们的实现方式。

  • 模型类通常通过INotifyPropertyChangedINotifyCollectionChanged接口提供属性和集合更改通知事件。 这使得他们可以很容易地在视图中绑定数据。 表示对象集合的模型类通常来自ObservableCollection<T>类。

  • 模型类通常通过IDataErrorInfoINotifyDataErrorInfo接口提供数据validation和错误报告。

  • 模型类通常与封装数据访问和caching的服务或存储库结合使用。

在Jason Dolinger的video中可以findMVVM的一个很好的介绍。 当我开始的时候,我和我保持了很长一段时间的video,这非常有用。

构build一个在底层Model上呈现一致外观的ViewModel可能会比看起来复杂得多。 这篇关于构buildViewModel对象的文章演示了如何构build一个ViewModel,并说明了可能遇到的一些问题 – 以及看起来像合理的解决scheme。 当我阅读时,处理藏品的部分丢失了,但是它仍然有一些有趣的地方。