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

时间:2011-03-24 15:49:30

标签: mvvm

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

根据我的理解, View 是愚蠢的,它只知道如何呈现传递给它的东西。

模型只是普通数据, ViewModel 就像两者之间的填充一样,它应该从模型中获取信息并将其传递到 View View 应该知道如何呈现它。或者反过来说,如果 View 中的信息发生变化,它应该将更改传递给模型

但我仍然不知道如何应用这个概念。有人可以解释一个非常简单的场景,以便我能掌握这个概念吗?我已经看了几个项目,但它仍然没有完全合理,所以如果有人能用简单的英语写出来,那就太好了。

5 个答案:

答案 0 :(得分:114)

我喜欢这样想:

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

模型是模拟应用程序域的对象,就像在业务对象中一样。你的应用程序是音乐商店吗?也许你的模型对象将是艺术家,专辑和歌曲。您的应用程序是组织结构图浏览器吗?也许您的模型对象将是经理和员工。这些模型对象与任何类型的视觉渲染无关,它们甚至与您正在将它们放入的应用程序直接相关 - 您的模型对象应该完全自己作为代表某种对象的一族对象域名。模型层通常还包括服务访问器等内容。

这将我们带到了Viewmodels。这些是什么?它们是模拟 GUI应用程序的对象,这意味着它们提供了视图使用的数据和功能。它们定义了您正在构建的实际应用程序的结构和行为。对于模型对象,域是您选择的任何域(音乐商店,组织图浏览器等),但对于viewmodel,域是图形应用程序。您的视图模型将封装应用程序所执行的所有操作和数据。他们将把对象和列表公开为属性,以及命令之类的东西。命令只是一个行为(最简单的方法调用)被包装到一个携带它的对象中 - 这个想法很重要,因为视图是由数据绑定驱动的,它将视觉控件附加到对象上。在MVVM中,您没有为按钮提供Click处理程序方法,而是将其绑定到命令对象(从viewmodel中的属性提供),该命令对象包含您单击时要运行的功能。

对我来说,最令人困惑的是:

  • 即使视图模型是图形应用程序的模型,它们也不直接引用或使用视觉概念。例如,您不希望在ViewModel中引用Windows控件 - 这些内容会出现在视图中。 ViewModels只是将数据和行为公开给控件或将绑定到它们的其他对象。例如 - 你有一个包含ListBox的视图吗?您的viewmodel几乎肯定会有一些收集。你的视图有按钮吗?你的viewmodel几乎肯定会有一些命令。
  • 有几种对象可以被视为“viewmodels”。要理解的最简单的视图模型是直接表示1:1关系中的控件或屏幕的视图模型,如“屏幕XYZ具有文本框,列表框和三个按钮,因此视图模型需要字符串,集合,和三个命令。“另一种适合viewmodel层的对象是一个模型对象周围的包装器,它赋予它行为并使它更适用于视图 - 这是你进入“厚”和“瘦”视图模型层的概念的地方。 “瘦”视图模型层是一组视图模型,它们将模型对象直接暴露给视图,这意味着视图最终会直接绑定到模型对象上的属性。这可以用于简单的只读视图之类的东西,但是如果你想拥有与每个对象相关的行为呢?您不希望在模型中使用该模型,因为模型与应用程序无关,它仅与您的域相关。您可以将它放在一个包装模型对象的对象中,并提供更多绑定友好的数据和行为。此包装器对象也被视为一个视图模型,并使它们产生一个“更厚”的视图模型层,您的视图永远不会直接绑定到模型类上的任何内容。集合将包含用于包装模型的视图模型,而不仅仅包含模型本身。

兔子洞更深入 - 有很多习惯用来像ValueConverters一样让MVVM保持工作,当你开始考虑Blendability,测试以及如何在你的app中传递数据时,有很多应用并确保每个视图模型都可以访问它所需的行为(这是依赖注入的来源),但希望以上是一个好的开始。关键是要将您的视觉效果,您的领域以及实际应用程序的结构和行为视为三种不同的事物。

答案 1 :(得分:18)

使用this incredibly helpful article作为来源,以下是查看 ViewModel 模型的摘要。


查看:

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

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

  • 视图可以自定义视图和视图模型之间的数据绑定行为。例如,视图可以使用值转换器来格式化要在UI中显示的数据,或者它可以使用验证规则为用户提供额外的输入数据验证。

  • 视图定义并处理UI视觉行为,例如可以通过视图模型中的状态更改或通过用户与UI的交互触发的动画或过渡。

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

注意:
由于视图模型不应该对视图中的特定可视元素有明确的了解,因此以编程方式操作视图中的可视元素的代码应该驻留在视图的代码隐藏中,或者封装在行为中。


查看型号:

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

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

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

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

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


型号:

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

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

  • 模型类通常通过INotifyPropertyChangedINotifyCollectionChanged接口提供属性和集合更改通知事件。这允许它们在视图中容易地数据绑定。表示对象集合的模型类通常派生自ObservableCollection<T>类。

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

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

答案 2 :(得分:15)

我在this series on MVVM中以“普通英语”的形式写出来。特别是,this diagram可能是最简单,最简短的解释。

话虽如此,基本上,“模型”是您的数据或业务规则。它真的不应该知道它将如何或在何处使用,特别是哪种技术不会使用它。 “模型”是应用程序的核心内容 - 它不应该担心应用程序是WPF,Silverlight,Windows Forms,ASP.NET等 - 它只是纯粹形式的“本身”。

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

但是,需要有一些东西可以将模型中的信息转换为某种形式,这些形式可供手头的技术使用 - 这就是ViewModel发挥作用的地方。例如,这通常将模型类“包装”为包含命令(用于运行逻辑),实现INotifyPropertyChanged(用于数据绑定支持)等的特定数据的“ViewModel”。就是这样 - 它就是使模型可供View使用的桥梁。

答案 3 :(得分:2)

在Jason Dolinger的视频here中可以找到MVVM的精彩介绍。

,当我开始的时候,我和我保持了一段时间的视频,这非常有用。

答案 4 :(得分:0)

构建一个ViewModel,它在底层模型上呈现一致的外观,可能比它看起来要复杂得多。这个article about building ViewModel objects演示了如何构建ViewModel,并说明了您可能遇到的一些问题 - 以及看似合理的解决方案。当我读到它时,关于处理集合的部分缺失了,但它仍然有一些有趣的点。