MVVM -- CallMethodAction 和 InvokeCommandAction

MVVM实践教程

算算,从事Silverlight和WPF的开发也有1年多的时间了,虽然时间不算长,虽然还没有突出的成就,但是感觉也还算一般。

但是,从头至今都没有去认真研究和使用过MVVM,虽然它被认为是Silverlight和WPF开发的最佳架构实践。

我想这里面还是有一些原因,就像一般开始我们始终都不会看好单元测试。直到有一天你体会到它的魅力,它的好处。

最近的项目,却不得不采用MVVM的模式:UI没有定,甚至服务端的Service都没有定,但是不能等到这些都做好才开始展开我们的开发工作。

于是,痛下决心研究MVVM的模式,在学习过程中,发现一些问题。MVVM的使用不仅仅是因为它需要新的思维,使View和ViewModel之间的交互变得更麻烦。这其中还有另外的原因,那就是参考资料不全。

一般网上的资料都是一片简单的教程,大体都是怎么使用命令,怎么使用Binding的方式来建立应用程序。这些几乎都出自John Smith的那篇WPF的文章。

而实际上,在开发中,还会遇到其他问题,例如页面切换,UI事件,并且简单的示例我们往往弄不清楚各个模块之间的职责和联系。因为不能有效实践,从而被认为会影响开发效率而不被采用。

这里,我将自己学习总结的知识整理成一篇完整的示例,有提供源代码,源代码包含比较完整的示例,不仅包含数据绑定和命令的使用,还包含UI事件和UI的切换。相信能解释大多数遇到的问题。

当然,如果你有更好的实践和建议,欢迎讨论……………

 

 1.MVVM设计模式简介

 

MVVM的设计模式最早于2005年由微软的WPF和Silverlight架构师John Gossman在他的博客中提到。以下是这篇文章的链接:

http://blogs.msdn.com/b/johngossman/archive/2005/10/08/478683.aspx

MVVM设计模式基于MVC这种将UI和逻辑分离的结构思想。传统的.NET平台下软件开发如ASP.NET和WPF/Silverlight大多数是基于CodeBehind这样的方式,我们往往将所有的代码全部写在后台代码文件中,例如UI操作,业务逻辑操作,IO,数据服务的调用等等。这虽然表面上有利于“开发效率”,实际上项目结构不清晰,各个模块之间紧密耦合,不利于扩展,不利于测试。

MV-X的思想,为.NET平台下的架构提供一种很好的实践。使我们可以构建更利于扩展,结构清晰,职责分明,易测试的软件项目。

但是目前MVVM模式还没有一个标准的实践,微软也还没有给出相对标准的方案。目前社区讨论的主要是MVVM的思想。在实际开发过程中形成了几种不同的风格。其中以Josh Smith的文章影响比较大:

http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

本篇提到的也主要是参考John Smith的思想。

2.采用MVVM设计模式的好处

在Silverlight或者WPF中采用MVVM的架构可以获得以下好处:

1. 项目可测试更高,从而可以执行单元测试

2. 将UI和业务的设计完全分开,View和UnitTest只是ViewModel的两个不同形式的消费者

3. 有助于我们区别并哪些是UI操作,哪些是业务操作,而不是将他们全混在CodeBehind中

3.项目结构介绍

以下是示例项目的结构截图:

以下是各模块之间的联系:

 

4.WpfMVVMSample.Foundation

提供一些基础类定义。

5.Model的职责

Model主要提供基础实体的属性以及每个属性的验证逻辑。

Model不包含数据的调用,但是可以包含简单的非数据调用的操作,如产生序列号或者合并字段。

对于WCF产生的客户端代理类,Models中应有与之相对应的类结构定义。

Model不依赖于任何项目。

6.IService和Services以及ServiceTest

IService是所有网络数据服务或者IO操作的服务接口。

IService中的数据访问方式以异步为主,见参考示例。

Service是真实的数据服务访问类,是IService的实现。ServiceTest是用于测试ViewModel的IService的实现

7.ViewModel的职责

ViewModel是MVVM架构中最重要的部分,ViewModel中包含属性,命令,方法,事件,属性验证等逻辑。为了与View以及Model更好的交互来满足MVVM架构,ViewModel的设计需要注意一些事项或者约束:

ViewModel的属性:ViewModel的属性是View数据的来源。这些属性可由三部分组成:

一部分是Model的复制属性。

另一部分用于控制UI状态。例如一个弹出窗口的控件可能有一个IsClose的属性,当操作完成时可以通过这个属性更改通知View做相应的UI变换或者后面提到的事件通知。

第三部分是一些方法的参数,可以将这些方法的参数设置成相应的属性绑定到View中的某个控件,然后在执行方法的时候获取这些属性,所以一般方法不含参数。

ViewModel的命令:ViewModel中的命令用于接受View的用户输入,并做相应的处理。我们也可以通过方法实现相同的功能。

ViewModel的事件: ViewModel中的事件主要用来通知View做相应的UI变换。它一般在一个处理完成之后触发,随后需要View做出相应的非业务的操作。所以一般ViewModel中的事件的订阅者只是View,除非其他自定义的非View类之间的交互。

ViewModel的方法:有些事件是没有直接提供命令调用的,如自定义的事件。这时候我们可以通过CallMethodAction来调用ViewModel中的方法来完成相应的操作。

8.View及Codebehind

View中使用Command:View中的Button等控件可以直接绑定Command属性调用ViewModel中的Command

View中使用CallMethodAction :一些不支持Command的控件,可以用一个CallMethodAction触发器来执行ViewModel中的方法。注意的是方法当中往往包含一些参数,这些参数一般可以通过给ViewModel设置相应的属性来绑定到相关的输入控件,如TextBox。

 View中使用DataTrigger:除了模型属性,还有一部分是状态属性,这往往是ViewModel通过属性更改的方式通知View做出相关的UI操作,例如触发一段动画,或者切换控件状态等等。这个时候可以使用一些触发器,当状态值不同时做出相应的UI变换。

 View的CodeBehind中初始化子View的ViewModel上下文:View一般由父View调用,所以View的ViewModel一般由父View来初始化。比如当点击人脉按钮,需要显示人脉的View的时候,就由主框架初始化人脉的ViewModel,并显示人脉的View。

View的CodeBehind中订阅子View的UI事件:除了通过状态属性的变更触发View中的触发器,看一种选择是在View的CodeBehind中订阅ViewModel的UI事件。

9.View及ViewModel交互模式总结

由以上解析我们可以总结出View和ViewModel的交互模式:

1. 父View在CodeBehind中初始化子ViewModel

2. 父View在CodeBehind中订阅子ViewModel的UI事件

3. 父View将子ViewModel赋值给子View的DataContext,并显示子View

4. 父View调用子ViewModel获取数据的方法,子ViewModel调用数据服务获取数据

5. ViewModel的数据通过Binding传递给View

6. View接受用户输入,并通过Command或者CallMethodAction交给ViewModel做业务处理

7. ViewModel处理完成之后触发UI事件或者更改状态属性通知父View

8. 父View做出View变换至新的界面

10. 依赖注入

ViewModel的职责是提供数据给View,并调用底层的数据服务。

为了解除ViewModel和BP的耦合,增加一层IService的接口定义,这也使得我们可以构造不同的IService实现来测试ViewModel。

但是View 在使用ViewModel的时候,ViewModel必须要使用IService对象,所以这里采用依赖注入。通过依赖注入来完全解除View以及ViewModel对于Service的依赖。

示例项目源代码下载:

http://files.cnblogs.com/hielvis/WpfMVVMSample.rar

转载: 快乐之王 http://www.cnblogs.com/hielvis/archive/2011/03/22/1991959.html

时间: 2024-10-29 19:10:48

MVVM -- CallMethodAction 和 InvokeCommandAction的相关文章

Prism4 文档翻译系列---第5章 实现MVVM模式

MVVM模式有助于清楚的区分应用程序界面的业务层和展现层.保持一个清晰的应用程序逻辑和UI分离有助于处理开发和设计过程中大量的问题,同时,使得应用程序的测试,维护,和扩展更加容易.MVVM也可以极大的提升代码的可重用性也可以使开发人员和设计人员在分别开发应用程序的某一部分时更方便的沟通交流. 运用MVVM模式,应用程序的UI和下层表现以及业务逻辑被拆分到三个单独到类中:视图,封装了UI和UI逻辑:视图模型,封装了展现逻辑和状态:模型,封装了应用程序的业务逻辑和数据. Prism包含了如何在Sil

MVVM - 事件转命令2

在使用MVVM模式时, 按照模式的规则是尽量不直接使用事件. 所以对于以前一直使用事件模式的同行来说确实有点头疼. 还好微软给我们提供了几种间接使用事件(命令)的方法, 下面我就来看看这几种方法: ICommand ICommand定义了一个接口, 使用它可以轻松的将实现ICommand的接口的命令绑定到包含命令(Command)的控件上(例如Button.Command), 在.net framework库中实现的这个接口的类不是很多, 我所知道的两个: RoutedCommand 和 Rou

Prism4 文档翻译系列---第6章 高级MVVM场景

在上一章中描述了如何通过将UI,表现逻辑,业务逻辑分别放到三个单独的类中(View,View Model,Model),实现这些类之间的交互(通过数据绑定,命令以及数据验证接口)以及实现一个策略来处理建筑和绑定的方式实现MVVM的基本元素. 通过使用实现MVVM的这些基本元素的方式可以支持应用程序中许多的应用场景.然而,您可能会遇到更复杂的场景,需要扩展基本MVVM模式或者需要应用更先进的技术.如果你的应用程序比较大或者比较复杂,这种情况很有可能会发生,但也可能在很小的应用中遇到这些场景.Pri

MVVM模式的UI界面数据返回问题

MVVM模式里面用户UI界面的数据返回问题,让我纠结了好几天,一直得不到数据,今天总算能取到UI界面的数据了! 我采用的是ListView显示数据和Prism模式,并且将数据显示成了大图标的样式,即水平显示,但是下面测试用的我就没有采用水平显示,做了简单Model. XAML 代码: <ListView ItemsSource="{Binding ProductList}" x:Name="lv" Margin="8,8,8,37.96"

WPF-MVVM模式学习笔记3——MVVM概念再次挖掘

通过上篇文章<WPF-MVVM模式学习笔记2--MVVM简单样例>中举了一个例子,我对MVVM大概有了一个比较浅显的意思.同时,看过前两篇文章的人,也知道我的这个系列的文章大多数来源于其他的博客,我其实只是起了一个汇总的作用,毕竟我也是在学习,肯定是要去网络上学习别人的笔记喽.本篇文章将以温故而知新的方式再次去理解MVVM,力求对MVVM的认识再深一个层次. 1.再看"M-V-VM" M:即Model,由现实世界抽象出来的模型. V:即View,视图,界面,该界面与用户输入

背水一战 Windows 10 (24) - MVVM: 通过 Binding 或 x:Bind 结合 Command 实现,通过非 ButtonBase 触发命令

原文:背水一战 Windows 10 (24) - MVVM: 通过 Binding 或 x:Bind 结合 Command 实现,通过非 ButtonBase 触发命令 [源码下载] 作者:webabcd 介绍背水一战 Windows 10 之 MVVM(Model-View-ViewModel) 通过 Binding 或 x:Bind 结合 Command 实现,通过非 ButtonBase 触发命令 示例1.ModelMVVM/Model/Product.cs /* * Model 层的实

WPF MVVM模式中,通过命令实现窗体拖动、跳转以及显隐控制

在WPF中使用MVVM模式,可以让我们的程序实现界面与功能的分离,方便开发,易于维护.但是,很多初学者会在使用MVVM的过程中遇到一个显而易见且无法回避的问题,那就是不同的窗体之间如何跳转?很多人在介绍MVVM的使用时,都没有明显提到该如何解决这一问题,不知是因为觉得太简单了还是其他原因. 博主根据自己的开发经验,写了一个简单的示例程序,介绍MVVM模式中,如何通过命令来控制窗体的跳转.拖动与显隐控制. 先看效果: 主窗体中只有一个按钮,点击该按钮后,可以打开新的窗. 新窗体可以为自定义样式窗体

折腾MVC的你,用Caliburn折腾过MVVM吗?

引言:什么是Caliburn ? 一个夜晚,一处教堂,人们忏悔结束后抬头看到一把宝剑插在一块石头上.石上字述“英格兰人,凡能从石头上拔出剑者,为王者!”,Caliburn就是英格兰人心中的石中剑,这把剑的主人是亚瑟王,但是在一次格斗中,这把剑被伯林诺王斩断. Caliburn用于一个MVVM产品的名称,其用意明显,作者是想借助于Caliburn的“锋利”来描述这个产品. Caliburn是一个功能全面的MVVM产品,全面的同时带来了代码量的庞大,作者在这个基础上做了一个精简版,名为 Calibu

WPF - MVVM - 如何将ComboBox的Selectchange事件binding到ViewModel

将所有的事件,属性,都映射到ViewModel中.好处多多,以后开发尽量用这种模式. 解决方法: 使用System.Windows.Interactivity.dll,添加该dll到项目引用 ? 1 xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" ComboBox映射的代码: <ComboBox VerticalAlignment="Ce