WPF MVVM 架构 Step By Step(6)(把actions从view model解耦)
到现在为止,我们创建了一个简单的MVVM的例子,包含了实现了的属性和命令。我们现在有这样一个包含了例如textbox类似的输入元素的视图,textbox用绑定来和view model联系,像点击button这样的行为用命令来联系。view model和model在内部通信。

但是在上面的架构中有一个问题,command类和view model有很严重的耦合。如果你记得command类的代码(在下面也有展示),在构造函数中传递view model对象,意味着这个command 类不能再其他的view model中重用。
public class ButtonCommand:ICommand
{
private CustomerViewModel _obj; public ButtonCommand(CustomerViewModel obj)
{
_obj = obj;
}
......
......
}

但是我们现在思考下什么是一个行为。它是一个来自于最终用户的像鼠标点击,按钮点击,菜单点击,按功能键等这样的事件。因此应该有一个方法去总结这些行为并且把他们用一个更通用的方式附加到view model里。
如果你认为逻辑行为是包含在方法和函数中的逻辑,那么什么是一个公用的方法去指向方法和函数呢?想想,那就是委托。
我们需要2个委托,一个用来CanExecute,另一个用来Execute。CanExecute返回一个布尔类型的值,因此用来验证,然后基于验证来允许和禁止用户接口。Execute当canexecute为真时执行。
public class ButtonCommand:ICommand
{
public bool CanExecute(object parameter)
{
//验证代码
} public void Execute(object parameter)
{
//执行逻辑
}
}
换句话来说,我们需要2个委托,1个返回布尔值的函数其他一个action返回空。因此正好我们可以创建一个func和一个action。通过用委托的方式,我们试着来创建一个通用的类。在command类中我们做了如下3个改变:
- 我们把构造函数中移走view model的对象,输入变为2个委托,一个是Func一个是Action。Func用来验证,Action用来执行。2个委托的值都通过构造函数来传递再传给类的私有变量。
- Func 委托 = CanExecute
- Action 委托 = What To Execute
public class ButtonCommand:ICommand
{
private Action _whatToExecute;
private Func<bool> _whenToExecute;
public ButtonCommand(Action what,Func<bool> when )
{
_whatToExecute = what;
_whenToExecute = when;
}
public bool CanExecute(object parameter)
{
return _whenToExecute();
} public void Execute(object parameter)
{
_whatToExecute();
} public event EventHandler CanExecuteChanged;
}
在model中,我们已经知道What to execute - CalculateTax,我们用了一个简单的函数(IsValid)用来验证customer类是否可用。
public class Customer
{
public void CalculateTax()
{
if (Amount > )
{
_Tax = ;
}
else if (Amount > )
{
_Tax = ;
}
else
{
_Tax = ;
}
} public bool IsValid()
{
return Amount != ;
}
}
在view model类,我们传递2个参数,一个Func,一个Action。
public class CustomerViewModel:INotifyPropertyChanged
{
private readonly ButtonCommand _objButtonCommandCommand; public CustomerViewModel()
{
_objButtonCommandCommand=new ButtonCommand(obj.CalculateTax,obj.IsValid);
} public ICommand CalClick => _objButtonCommandCommand; private Customer obj = new Customer();
}
这让架构变得更好而且因为command类能用通用的方法和任何view model来结合使用而解耦。下面就是改善后的架构,注意现在view model怎么和command类通过委托来通信的。

PRISM是一个MVVM架构中不错的框架。PRISM主要的用处是用来模块化开发,它有一个不错的delegateCommand类,比我们自己创建自己的command类要好不少。
PRISM: http://www.microsoft.com/en-in/download/details.aspx?id=42537
WPF MVVM Step By Step 原文: http://www.codeproject.com/Articles/819294/WPF-MVVM-step-by-step-Basics-to-Advance-Level
WPF MVVM 架构 Step By Step(6)(把actions从view model解耦)的更多相关文章
- [译]WPF MVVM 架构 Step By Step(5)(添加actions和INotifyPropertyChanged接口)
应用不只是包含textboxs和labels,还包含actions,如按钮和鼠标事件等.接下来我们加上一些像按钮这样的UI元素来看MVVM类怎么演变的.与之前的UI相比,这次我们加上一个"C ...
- WPF MVVM 架构 Step By Step(4)(添加bindings - 完全去掉后台代码)
之前的改进已经挺棒的,但是我们现在知道了后台代码的问题,那是否可能把后台代码全部去除呢?这时候就该WPF binding 和 commands 来做的事情了. WPF就是以超吊的binding,com ...
- WPF MVVM 架构 Step By Step(3)(把后台代码移到一个类中)
我觉得大部分开发者应该已经知道怎么去解决这个问题.一般都是把后台代码(GLUE code)移动到一个类库.这个类库用来代表UI的属性和行为.任何代码当被移到一个类库中时都可以被编译成一个DLL,然后可 ...
- WPF MVVM架构 EF、WCF、IOC 设计示例经典
概要 该演示项目利用WPF应用程序构建的MVVM架构示例, 运用了Unity容器接口注入, MVVM的经典设计, 后台利用的EF+WCF. 后台实现: 从数据库生成的emdx 结合上下文进行数据交互, ...
- WPF MVVM 架构 Step By Step(2)(简单的三层架构示例及粘合代码GLUE code)
我们第一步就是去了解三层架构和问题然后去看MVVM是怎么去解决这些问题的. 现在,感觉和事实是完全不同的两个东西.当你看到三层架构的框图的时候,你会觉得每层的职责被分配的很好.但是当你你真的去写代码的 ...
- WPF MVVM 架构 Step By Step(1)(介绍)
生命就是我们从孩子开始,经过不断的学习成为成熟的成年人的进化过程.这和软件的架构有着异曲同工之妙,我们从基础的架构开始,随着需求和环境的变化不断的进化. 如果你去问任何一个.net开发者,什么是最基础 ...
- C# WPF - MVVM实现OPC Client管理系统
前言 本文主要讲解采用WPF MVVM模式设计OPC Client的过程,算作对于WPF MVVM架构的学习记录吧!不足之处请不吝赐教,感谢! 涉及知识点 C#基础 Xaml基础 命令.通知和数据绑定 ...
- WPF Step By Step 系列-Prism框架在项目中使用
WPF Step By Step 系列-Prism框架在项目中使用 回顾 上一篇,我们介绍了关于控件模板的用法,本节我们将继续说明WPF更加实用的内容,在大型的项目中如何使用Prism框架,并给予Pr ...
- WPF Step By Step 系列 - 开篇 ·
WPF Step By Step 系列 - 开篇 公司最近要去我去整理出一个完整的WPF培训的教程,我刚好将自己学习WPF的过程和经验总结整理成笔记的方式来讲述,这里就不按照书上面的东西来说了,书本上 ...
随机推荐
- TCP/IP协议精华笔记
1.简介 TCP/IP协议并非单指TCP协议.IP协议,它是一组包括TCP协议和IP协议,UDP(User Datagram Protocol)协议.ICMP(Internet Control Mes ...
- iOS 制作自动打包脚本 Xcode8.3.2
本文包含以下内容: 前言 1.shell脚本的编写 2.xcodebuild命令 3.完整的可用示例 参考资料 前言 做iOS开发,打包APP是比较频繁的事情,每次都手动去配置一堆东西确实是比较乏味. ...
- OC 动态类型和静态类型
多态 允许不同的类定义相同的方法 动态类型 程序直到执行时才能确定所属的类 静态类型 将一个变量定义为特定类的对象时,使用的是静态形态 将一个变量定义为特定类的对象时,使用的是静态类型,在编译的时候就 ...
- 文件查找---find
文件查找(find) 1 find 简单的说,就是实时查找指定的内容或条件.特点:最新.最快.最准确. 用法:find [查找路径] [查找条件] [找到后进行的动作] eg. find /e ...
- SSH小结
工作有一段时间了,经常用SSH登录远程机器,但对原理一直不是很了解,所以查阅了一些资料,写个小结. 一. SSH是什么? SSH的全称是Secure Shell, 是一种"用来在不安全的网络 ...
- c++ STL stack & queue
Stack 主要的方法有如下: empty() 堆栈为空则返回真 pop() 移除栈顶元素(不会返回栈顶元素的值) push() 在 ...
- [刷题]算法竞赛入门经典(第2版) 6-9/UVa127 - "Accordian" Patience
题意:52张牌排一行,一旦出现任何一张牌与它左边的第一张或第三张"匹配",即花色或点数相同,则须立即将其移动到那张牌上面,将其覆盖.能执行以上移动的只有压在最上面的牌.直到最后没有 ...
- [刷题]算法竞赛入门经典(第2版) 4-3/UVa220 - Othello
书上具体所有题目:http://pan.baidu.com/s/1hssH0KO 代码:(Accepted,0 ms) //UVa 220 - Othello #include<iostream ...
- Mongodb安装启动详解
最近在倒腾node+mongodb,安装mongodb的时候开始遇到很多问题,然后折腾了好几次,直到可以很顺利完成安装 ,所以把安装的过程记录下来. 线上系统基本上都是linux的,所以只安装了lin ...
- 详解Google Chrome浏览器(操作篇)(下)
开篇概述 由于最近忙于公司产品的架构与研发,已经三个多月没有写博客了,收到有些朋友的来信,问为什么不及时更新博客内容呢,他们说他们正期待着某些内容.对此,非常抱歉,那么我在此也给各位朋友一些承诺,从即 ...