Model-View-ViewModel是一种架构模式,主要在WPF、Silverlight和WP7开发里使用,它的目标是从视图层移除几乎所有代码隐藏(code-behind)。交互设计师可以专注于使用XAML表达用户体验需求,然后创建和视图模型的绑定,而视图模型则是由应用程序开发者开发和维护的。
MVVM是更加通用的Presentation模式的一个具体实现。MVVM视图模型包含概念模型而不是数据模型,所有业务逻辑和其它操作都是在模型和视图模型里完成的。有很多框架可以做到这点,其中一些是:
开源的
- PRISM:由微软提供,和MEF/Unity一起用于依赖注入,支持组合命令,可以扩展。MSDN上有详细的教程和演练。
- MVVM Light Toolkit:有visual Studio和Expression Blend的项目和项的模板。更多信息请看这里,另外可以参考VS和Expression Blend的使用教程。
- Caliburn Micro:支持视图模型先行(ViewModel-First)和视图先行(View-First)两种开发方式,通过co-routine支持异步编程。
- Simple MVVM Toolkit:提供VS项目和项的模板,依赖注入,支持深拷贝以及模型和视图模型之间的属性关联。
- Catel:包含项目和项的模板,用户控件和企业类库。支持动态视图模型注入,视图模型的延迟加载和验证。还支持WP7专用的视图模型服务。
闭源的
- Intersoft ClientUI:付费的,只支持WPF和Silverlight,但是,除了MVVM框架,它还提供其它一些特性。
- Vidyano:免费但不开源。带有实体映射/虚拟持久化对象(数据容器),业务规则以及内置基于ACL的安全特性。
若想了解MVVM,可以参考以下资料:
- Laurent Bugnion的《Understanding MVVM Pattern》和《Deep Dive MVVM》
- 微软Silverlight组的《Understanding the MVVM Pattern in Silverlight Applications》
- Erik Lebel在InfoQ上的视频演讲《Presentation Pattern》
使用MVVM的最大好处之一是分离关注点,以便用户体验设计师和应用程序开发者可以并行工作。另一方面,相关的担忧包括它对于UI操作比较简单的情况有点杀鸡用牛刀的感觉,数据绑定有点难以调试,以及大量使用数据绑定可能带来性能问题等等。
Jonathan Allen在评论里提到几点错误使用MVVM的征兆:
1. 你的模型和视图模型名字相同。
视图模型不应该是对模型的包装。视图模型的职责是外部服务的请求中介,比如加载和保存数据。而数据本身,以及验证和大多数业务逻辑应该放在模型里。
我经常强调这点。每当你创建一个视图模型包装一个模型,你就在你的API里引入一个巨大漏洞。具体地,任何直接引用这个模型的东西都可能以视图模型无法察觉的方式改变某个属性,因此UI也不会有相应的改变。同样地,模型里计算字段的任何更改也不会回传给视图模型。
2. 你的视图和视图模型名字相同。
理想的情况下,视图模型是不知道使用它们的视图的,尤其是WPF应用程序有多个窗口共享相同的视图模型。
对于比较小型的应用程序来说,整个应用程序可能只需一个视图模型。对于比较大型的应用程序来说,主要功能可能需要一个视图模型,每个次要方面也需要一个,比如配置管理。
3. 你没有代码隐藏。
代码隐藏既非一个好的东西,亦非一个坏的东西。它只是一个用来放置和视图或控件相关的逻辑的地方。因此,当我看到一个视图没有任何代码隐藏,我就会马上检查是否存在以下问题:
- 视图模型是否通过名字接触了特定的控件?
- 视图模型是否通过命令参数访问控件?
- 是否使用了EventToCommand或其它可以导致泄露的行为而不是简单的事件处理程序?
MVVM Light的EventToCommand很有问题,因为它会使得控件从屏幕移除之后无法被垃圾回收。
4. 视图模型监听属性更改通知
如果一个模型的的生命周期比监听它的事件的视图模型长,那么可能导致内存泄露。不同于视图有个Unloaded事件,视图模型对于生命周期管理没有很好的方案。因此如果它们关联到存活期比它们更长的视图模型的事件,视图模型将会出现泄露。
查看英文原文:MVVM Frameworks For .NET