设计模式-使用 Model-View-ViewModel的问题和解决方案

Windows Presentation Foundation (WPF) 和 Silverlight 提供了丰富的 API 用来构建现代应用程序,但是了解并和谐一致地应用所有 WPF 特性来构建设计精良、易于维护的应用程序可能非常困难。从何处入手?什么样的方法才算是正确的应用程序设计方法?

Model-View-ViewModel (MVVM) 设计模式描述了构建 WPF 或 Silverlight 应用程序的常用方法。它还是一款构建应用程序的强大工具,以及一种与开发人员讨论应用程序设计的通用语言。虽然 MVVM 确实很有用,但它发展时间不长,用户尚未形成正确的认识。

MVVM 设计模式什么时候是适用的,什么时候又是不必要的?应该如何设计应用程序的结构?ViewModel 层有多少代码要编写和维护,有什么替代方式能够减少 ViewModel 层的代码量?如何妥善处理 Model 中的相关属性?应该如何在 View 中显示 Model 中的集合?应该在哪里实例化 ViewModel 对象,并将其挂接到 Model 对象?

在本文中,我将解释 ViewModel 的工作原理,并讨论在您的代码中实现 ViewModel 的优缺点。我还会介绍一些具体的示例,演示如何使用 ViewModel 作为文档管理器,以便在 View 层中显示 Model 对象。

Model、ViewModel 和 View

到目前为止,我设计过的每个 WPF 和 Silverlight 应用程序都具有相同的高层组件设计。Model 是应用程序的核心,需要投入大量精力,按照面向对象的分析和设计 (OOAD) 最佳做法进行设计。

对我来说,Model 是应用程序的核心,代表着最大、最重要的业务资产,因为它记录了所有复杂的业务实体、它们之间的关系以及它们的功能。

Model 之上是 ViewModel。ViewModel 的两个主要目标分别是:使 Model 能够轻松被 WPF/XAML View 使用;将 Model 从 View 分离并对 Model 进行封装。这些目标当然非常好,但是由于一些现实的原因,有时并不能达到这些目标。

您构建的 ViewModel 知道用户在高层上将如何与应用程序交互。但是,ViewModel 对 View 一无所知,这是 MVVM 设计模式的重要部分。这使得交互设计师和图形设计师能够在 ViewModel 的基础上创建优美、有效的 UI,同时与开发人员密切配合,设计适当的 ViewModel 来支持其工作。此外,View 与 ViewModel 的分离还使得 ViewModel 更有利于单元测试和重用。

为了在 Model、View 和 ViewModel 层之间实施严格的分离,我喜欢将每一层构建为一个单独的 Visual Studio 项目。与可重用的实用工具、主要的可执行程序集以及任何单元测试项目(您有大量这些内容,对吗?)结合之后,这会产生大量项目和程序集,如图 1 所示。


图 1 MVVM 应用程序的组成部分

由于这种严格分离的方法会产生大量项目,因此它显然最适合大型项目。对于只有一两位开发人员的小型应用程序来说,这种严格分离带来的好处可能无法抵消创建、配置和维护多个项目所带来的不便,因此仅仅将您的代码分离到同一个项目的不同命名空间中,可能比充分隔离更好用。

编写和维护 ViewModel 并不容易,不应轻率地对待。但是,一些最基本问题(MVVM 设计模式什么时候是适用的,什么时候又是不必要的)的答案经常包含在您的域模型中。

在大型项目中,域模型可能非常复杂,需要精心设计数以百计的类,使它们能够在任何类型的应用程序(包括 Web 服务、WPF 或 ASP.NET 应用程序)中顺畅地结合在一起。Model 可能由几个相互配合的程序集组成,甚至在超大型组织中,域模型有时是由一个专门的开发团队构建和维护的。

如果您有一个复杂的大型域模型,则引入 ViewModel 层几乎总是会带来好处。

另一方面,域模型有时很简单,可能仅仅是覆盖在数据库上的一个薄层。类可以自动生成,而且通常会实现 INotifyPropertyChanged。UI 通常是一系列可供编辑的列表或表格,允许用户对底层数据进行操作。Microsoft 工具集一直都极其擅长轻松快捷地构建这类应用程序。

如果您的模型或应用程序是这种类型的,则 ViewModel 很可能会带来难以接受的高开销,而对您的应用程序设计并没有足够的好处。

尽管如此,即使在这些情况下,ViewModel 也仍然有其价值。例如,ViewModel 非常适合用来实现“撤消”功能。另外,您也可以选择在应用程序的某个部分(例如文档管理,我将在后面讨论)使用 MVVM 直接向 View 提供 Model。

为什么要使用 ViewModel?

即使 ViewModel 看起来适合您的应用程序,在开始编写代码之前,仍然还有问题需要解答。其中最重要的问题是如何减少代理属性的数量。

MVVM 设计模式将 View 从 Model 分离,这种做法是该模式的一个重要且有价值的方面。因此,如果 Model 类有 10 个属性需要在 View 中显示出来,则 ViewModel 最终通常会有 10 个等效的属性,这些属性只是代理了对底层模型实例的调用。这些代理属性在设置时通常会引发属性更改事件,通知 View 该属性已更改。

并非每个 Model 属性都要有 ViewModel 代理属性,但是每个需要在 View 中显示的 Model 属性通常都有一个代理属性。代理属性通常如下所示:

public string Description {
  get {
   return this.UnderlyingModelInstance.Description;
  }
  set {
   this.UnderlyingModelInstance.Description = value;
   this.RaisePropertyChangedEvent("Description");
  }
}

时间: 2024-08-31 21:54:14

设计模式-使用 Model-View-ViewModel的问题和解决方案的相关文章

Model/View Programming

http://doc.qt.digia.com/4.7/model-view-programming.html Model/View Programming Introduction to Model/View Programming Qt 4 introduced a new set of item view classes that use a model/view architecture to manage the relationship between data and the wa

NBearV3教程——MVP(Model/View/Presenter)篇

版本 1.1 [2007-2-12] 简介 本教程在<NBearV3 Step by Step教程--IoC篇>的基础上,演示如何基于NBearV3的MVP模块实现基于NBear的IoC的MVP模式的过程.您将看到,利用封装了NBear的IoC模块的NBear.MVP模块,不仅能大大加强系统表现层的可测试性,同时能充分利用NBear已有的IoC模块获得依赖注入能力及基于IoC的分布式服务支持. 注:在阅读本文之前,建议读者先阅读<NBearV3 Step by Step教程--IoC篇&

django model去掉unique_together报错的解决方案_python

事情是这样的,我有一个存储考试的表 class Exam(models.Model): category = cached_fields.ForeignKeyField(Category) name = models.CharField(max_length=128) date = models.DateField() created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(au

6 个值得好好学习的 JavaScript 框架

常言道,条条大路通罗马,可是那一条适合我呢? 由于用于构建前端页面等现代技术的出现,JavaScript 在 Web 开发社区早已是如雷贯耳.通过在网页上编写几个函数并提供执行逻辑,可以很好的支持 HTML (主要是用于页面的 表现 或者 布局).如果没有 JavaScript,那页面将没有任何 交互特性 可言. 现在的框架和库已经从蛮荒时代崛起了,很多老旧的技术纷纷开始将功能分离成模块.现在不再需要在整个核心语言中支持所有特性了,开发者允许所有用户创建库和框架来增强核心语言的功能.这样,语言的

理解javascript中的MVVM开发模式

          MVVM的全称是Model View ViewModel,这种架构模式最初是由微软的MartinFowler作为微软软件的展现层设计模式的规范提出,它是MVC模式的衍生物,MVVM模式的关注点在能够支持事件驱动的UI开发平台,例如HTML5,[2][3] WindowsPresentation Foundation (WPF), Silverlight 和 t ZK framework,Adobe Flex.           对这种模式的实现,大部分都是通过在view层声

Silverlight 4 MVVM开发方式(一)小黑端

转自http://www.dotblogs.com.tw/help/archive/2010/07/27/16844.aspx   一开始接触WPF和Silverlight就对MVVM的开发方式非常有兴趣, MVVM是Model - View - ViewModel的缩写,Model就是资料,View就是介面,ViewModel负责控制介面与资料, 是利用DataBinding的机制所产生出的设计模式,因此只适用于Silverlight和WPF. 此开发方式的目的就是让程式开发人员和画面设计人员

浅谈JavaScript前端开发的MVC结构与MVVM结构_javascript类库

MVCModel–View–Controller (MVC)是一种把信息展现逻辑和用户交互分离的计算机用户界面开发模式:Model包含应用的数据和业务逻辑:Controller负责把用户的输入,转换为命令传递给Model和View;这是维基百科的解释: 这种模式最初是由Trygve Reenskaug在使用Smalltalk-80(1979)工作时设计的,刚开始叫做Model-View-Controller-Editor:后来通过<Design Patterns: Elements of Reu

认识Knockout及如何使用Knockout绑定上下文_javascript技巧

Knockout介绍 Knockout简称ko,是一个轻量级的javascript类库,采用MVVM设计模式(即Model.view.viewModel),简单优雅的实现了双向绑定,实时更新,帮助您使用干净的数据模型来创建丰富的.响应式的用户界面. Knockout有三大核心特性:     1.优雅的依赖跟踪(Elegant dependency tracking):任何时候数据模型的变化都会自动更新相应的UI部分:     2.声明式绑定(Declarative bindings) : 简单的

DotNet 资源大全中文版(Awesome最新版)

Awesome系列的.Net资源整理.awesome-dotnet是由quozd发起和维护.内容包括:编译器.压缩.应用框架.应用模板.加密.数据库.反编译.IDE.日志.风格指南等. 算法与数据结构(Algorithms and Data structures) Algorithmia -.NET 3.5及更高版本的算法和数据结构库. 算法包含复杂的算法和数据结构,如图,优先级队列,命令,撤消重做等. C# Algorithms - 标准数据结构和算法的C#即插即用类库项目. 它包含35多个数

Vue.js 和 MVVM 的注意事项_javascript技巧

MVVM 是Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式,其核心是提供对View 和 View Model 的双向数据绑定,这使得View Model的状态改变可以自动传递给 View,这就是所谓的数据双向绑定. Vue.js 是一个提供 MVVM 风格的双向数据绑定的 Javascript 库,专注于View 层.它的核心是 MVVM 中的 VM,也就是 ViewModel.ViewModel负责连接 View 和 Model,保证视图和数据的一致性,这种轻