没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
WPF 中 MVVM 模式原理分析与实践
发布者:51CTO 日期: 2009-07-24 13:54:00
浏览次数:83 (共有 0 条评论) 查看评论 | 我要评论
1, 前提
可以说 MVVM 是专为 WPF 打造的模式, 也可以说 MVVM 仅仅是 MVC 的一个变种, 但
无论如何, 就实践而言, 如果你或你的团队没有使用"Binding"的习惯, 那么研
究 MVVM 就没有多大意义.
另外,个人觉得, 使用 Command 以及打造一种合理的简化的方式去使用 Command
也与使用 Binding 一样重要.
2, 诞生
为了解决现实世界中的问题,我们需要将现实世界中的事物加以抽象, 然后得到
了 Domain Object, 无论贫血的还是富血的, 我们都可以简单地把他们归结为"
由现实世界抽象出来的模型", 也就是我们的 model, 也就 M-V-VM 中的"M"。
但其无法与我们的用户进行交互, 所以, 我们需要为其创建一个界面(视图,
View), 该视图可以与用户输入设备进行交互, 这很棒, 但问题是如何将 View
与我们的 model 关联起来? Binding 便可以发挥作用了, 比如视图上的某一个文
本框中的文本和 Model 中的"用户名"关联起来, 用户便可以通过操作该文本框
来访问和修改 Model 的"用户名"了。
这是极其简单的情况, 但实际编程时我们发现, Model 中的属性(与方法)往往不
那么容易与 View 中的界面控件关联起来, 比如, "类型不匹配": 界面控件所需
要的类型与模型中属性提高的类型不匹配. "需要额外操作": 模型中的数据需
要经过一些额外的处理才能传给视图,反之亦然. 此时, 我们意识到 View 似乎
需要一个"Helper"类来处理一些额外工作.
这 个 helper 所包含的代码可以放在除了 Model 外的很多地方(我们现在不考虑
贫血富血之类的争论), 比如 View 中, 记得自己刚学习窗体程序开发时就是这
么干的, 将绝大多数处理逻辑放在那个所谓的 CodeBehind 中. 后来,正如大家
在各种设计模式书籍中所看到的一样,为了将 View 和 Model 剥离开来,实现 view
可替换(比如你可以讲自己精心设计的软件同时运行于 窗体程序,Web 甚至
Mobile 上), 便有了 MVC. 有了 MVC 以后似乎就开始滋生 M-V-XXX 之类的争论与
变种模型, 比如 MVP 以及这里的 MVVM,甚至 MVP 也有着 Supervising Controller
与 Presentation Model 两种方式. 但主要围绕两个问题,一是 model 与 view 之
间的关系, 完全隔离的?单向的还是双向的? 二是这个"XXX"需要完成哪些功能,
简单流程调度?复杂规则处理? OK,这些争论都没有关系, 是否采用某种模式取
决于你的开发所处的环境(比如语言特性,框架特性)以及你的业务特性以及所面
临的主要变化点等等。
但与 MVC,MVP 所不同的是,MVVM 的引入不仅仅是技术上的原因(解除耦合应对变
化等老生常谈),另外一个很大原因是:软件团队开发方式的改 变.如果你做过一
段时间的 WPF 项目开发的话,你可能会有比较明显的感觉:在 View 层打造上,如何
分配程序员和美工的工作.在继续阅读之前,大家可以看 看我以前的一篇文章"
在 UI Designer 与 Developer 之间". 以前我们团队采用的便是"集成模式", 我
便兼职了其中的"Integrator"角色.这还不错.但说实在的,这仅仅是一个在特殊
情况下不得已而为之的暂时方案,所以我们付出了很大的努力开始 转向"收割模
式"了,要转向这个模式,至少需要两个基本条件:
(1)你拥有能够熟练运用 Blend 等工具能为程序员输出 XAML 的美工, 他专注于纯
粹的 UI/UE, 另外他还必须具有一定的"程序员"思维.以便输出的东西能很好地
作为程序的一部分而运转起来,而不是仅仅"看上去"是那样的。
(2)你需要能够脱离 View 层但仍能编写出高质量代码的程序员。
幸运的是, 我们在努力创造条件 1,并取得了很好的效果.(你可以招一个具有
Flash 脚本编写经验的并且有极大的学习热情的美工人员, 并对他进行 Blend 的
相关培训). 而 MVVM 模式为我们实现第二个条件提供了极大的便利. 为什么
MVC/MVP 模式不行而 MVVM 可以呢? 很简单, 在 MVC 和 MVP 模式中, View 层都具
有很多代码逻辑, 开发 View 层的是程序员, 虽然 UI/UE 团队会做很多工作, 但
这个层的"实现者"仍然是程序员. 在以前的开发中,其工作得很好, 而在 WPF 开
发中程序员对 View 层的展现显得力不从心了,美工(指符合上面条件 1 的美工)
虽然很擅长, 但他会说"可惜我不会程序".于是, 我们需要一种方式将 View 层
的代码逻辑抽取出来,并 View 层很纯粹以便完全让美工去打造它.相应地, 需要
将 View 层的相应逻辑抽取到一个代码层上,以便让程序员专注在这里。
回想一下, 我们只所以要在 View(Xaml)背后写一些代码(C#), 无非是想传递一
些数据以及传递数据时的数据的处理或在用户与界面控件进行交互时执行一些
操作, 最简单的例子是在 MVC 中当界面发生交互时 View 去调用 Controler 中的
某个方法, 以便将该操作的相应"指示"传递到"后台"去. 在以前的技术中, 这
样的"衔接性"的代码是必须的. 而在 WPF 中, 则可以通过另外的技术来进行层
与层之间的"衔接", 这就是"Binding" 和"Command", 以及稍后我们会提到的
"AttachBehavior". 通过 Binding, 我们可以实现数据的传递; 通过 Command,
我们可以实现操作的调用.(AttachBehavior 的作用稍后再谈). Binding 和
Command 是可以写在 XAML 中的, 这样看来 XAML 后面对于的 CS 文件可以被完全
抛弃或不予理会了. 这样的 XAML 文件正是美工所需要的. 而这些对于 Binding
以及 Command 的定义描述以及其他相关信息的代码应该放在那里呢, 当然不是
View, 更不是 Model, 是"ViewModel". ViewModel 是为这个 View 所量身定制的,
它包含了 Binding 是所需的相关信息,比如 Converter 以及为 View 的 Binding
提供 DataContext, 它包含了 Command 的定义以便 View 层可以直接使用, 另外,
它还是一个变种的 Controler, 它得负责业务流程的调度。
于是, 便有了这副图, 然后, 正如"时势造英雄"所言, MVVM 就诞生了.
3, ViewModel 与单元测试
如果你是一名正在使用 MVVM 模式打造软件的程序员, 那么我劝你尽快忘掉 View.
你所面对的是这样一个模式"UnitTest-ViewModel-Model"(这并非一个模式, 仅
仅是我为阐述观点而暂时如此表述的)。
记得曾经有一个 Model-View-AbstractView 模式, 而 MVVM 中的 VM 实际也是一个
AbstractView: the abstraction of view. 它是一个抽象的 View, 具有一个
View 的灵魂,而不具备相应的可视化控件而已. 所以对于程序员而已, 打造这
样一个抽象的 VM 就可以认为是完成 View 层的打造了.而当美工完成无数控件组
成的实际的 View 后, 我们就可以用 Binding 和 Command 这样的黏合剂将这个抽
象的 View 和实际的 View 黏合在一起了。
那么在黏合之前, 我们怎么知道自己的 VM 是否正常工作呢? 单元测试!
在说明对于 ViewModel 进行单元测试的重要性之前, 送给大家一句话: "View
and Unit Test are just two different types of ViewModel consumers" (Josh
Smith). 如果我们将 ViewModel 看作生产者, 那么 View 和 Unit Test 都是具有
同等地位的消费者而已. 并且 UnitTest 相比于 View 而言具备更大的消费能力.
或者你可以简单的认为 View 也仅仅是一种不太推荐的测试方式而已. 所以要实
施好这个模式, 那么对 ViewModel 的单元测试就是必须的了,并且这个测试要不
依赖于任何 UI 控件. (那么不是不对应 ViewModel 的开发是不是就应该通过测试
来驱动了?TDD?)
4, AttachBehavior
一般情况下利用 Command, Binding, AttachProperty 等 WPF 特性, View 和
ViewModel 之间能配合工作得很好. 假设我们有一个 Button, 当该Button 被点
击的时候我们要完成一些操作, 很简单, 将该操作封装成一个 Command 并绑定
到该 Button 上就可以了, 但如果我们要在 Button 被 Load 的时候执行另外一些
操作呢? 由于 Button 没有直接被 Load 事件所触发的 Command, 所以不能使用
Command 了. 不能直接将 Load 事件处理器写在 Button 所在的 Xaml 所对应的 CS
文件里, 这和我们刚才对 MVVM 的设计是相矛盾的. 一个不太好的方案是继承一
下 Button, 并撰写一个由 Load 所触发的 Command, 这可行, 但明显不好. 正如
一个控件没有某个属性并且在不继承的情况下而采用 AttachProperty 一样, 我
们可以采用 AttachBehavior. AttachBehavior 不是 WPF 特性, 它仅仅是一个最
佳实践, 一个 Pattern. 关于 AttachBehavior 语法如何书写, 请参考 :
http://www.codeproject.com/KB/WPF/AttachedBehaviors.aspx
基于 MVVM 模式开发 Silverlight 3 应用(理论篇)
http://developer.51cto.com 2009-12-21 09:22 朱先忠 编译 51CTO.com 我要评论(0)
在设计 Silverlight 应用程序时,我们所关心的核心问题是紧密耦合问题,以及单元测试的
问题。解决这个问题的思路在于分层模式,而 WPF 社团推出的 MVVM 模式作为 MVC 与 MVP 模
式的改进,能够很好的解决这些问题。
【51CTO 精选译文】在本系列文章中,我们将通过一个简单的 Silverlight 3.0 实例向
您展示如何通过使用当前成熟的应用程序设计模式,即“模型—视图—视图模型” 模式,
来实现用户界面层与其相关数据层的分离设计。本文原文讲述内容针对 Silverlight 2.0,
不过据译者观察,Silverlight 2 和 Silverlight 3 在架构方面没有太大变化,此文内容可
以通用。
一、引言
当前,Silverlight 的正式版本为 3.0,基于此技术的应用程序数量正在急剧增长。但
是,到目前为止,Silverlight 3.0 模板所支持的基本结构却意味着用户界面(UI)与其所
需要的任何数据间是紧密集成的关系。虽然这种紧密集成的技术对于学习 Silverlight 本身
来说是有益的,但是,当使用之来开发真实的应用程序时却会为测试、重构和维护等工作带
来巨大的困难。
二、紧耦合设计带来的问题
在设计 Silverlight 应用程序时,我们所关心的核心问题是紧密耦合问题。造成这种紧
密耦合的原因是:开发过程中,我们很容易把应用程序的各个层混合在一起。当一个层中拥
有另一个层中所需要的大量信息时,说明你的应用程序正处于紧密耦合状态。我们不妨来考
虑一个简单的 Silverlight 数据输入应用程序,假定此程序允许你查询某个城市的待售房屋
信息。在一个紧密耦合的应用程序中,您可能会在用户界面中的一个按钮的 Click 事件处理
程序中定义执行搜索的查询操作。于是,当规则改变或搜索语义发生变化时,无论是数据层
还是用户界面层都必须进行相应的更新。
这种情况势必导致代码质量和编码复杂性的问题。每当数据层改变时,你必须进行同步
更新并测试应用程序,以便确保所做的更改没有与发生的变化相违背。当一切都紧密地绑在
一起时,在一个应用程序某一部分中的任何变化都可能会导致在代码的其他部位发生相应的
变化。当你使用 Silverlight 开发简单的程序,例如一个电影播放器或菜单组件,紧密耦合
的应用程序组件不太可能造成大的问题。但是,随着项目尺寸的不断增大,你会感觉到麻烦
越来越多。
另一个问题是单元测试的问题。当一个应用程序是紧密耦合型的,你只能进行应用程序
的功能(或用户界面)测试。同样,这对于一个小项目不是什么问题,但是随着项目规模和
复杂性的不断增长,能够分层测试应用就变得非常重要。请记住,单元测试并不只是确保当
在一个系统中使用它时此单元能够工作,而是需要确保它能够在一个系统中继续不断地使用。
对系统各个局部进行单元测试可以保证,随着系统的变化,在这个过程中会更早期地发现问
题,而不是和仅使用功能测试那样在最后才发现问题。因此,回归测试(例如,针对一个系
统的每一个版本都进行单元测试)就变得至关重要—它可以确保系统中新增加的小变化不至
于造成一系列的错误。
剩余15页未读,继续阅读
资源评论
- u0106855622013-09-02感谢分享,某部分观念有帮到我
jyluyw
- 粉丝: 0
- 资源: 1
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功