到现在为止,我们创建了一个简单的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解耦)的更多相关文章

  1. [译]WPF MVVM 架构 Step By Step(5)(添加actions和INotifyPropertyChanged接口)

    应用不只是包含textboxs和labels,还包含actions,如按钮和鼠标事件等.接下来我们加上一些像按钮这样的UI元素来看MVVM类怎么演变的.与之前的UI相比,这次我们加上一个"C ...

  2. WPF MVVM 架构 Step By Step(4)(添加bindings - 完全去掉后台代码)

    之前的改进已经挺棒的,但是我们现在知道了后台代码的问题,那是否可能把后台代码全部去除呢?这时候就该WPF binding 和 commands 来做的事情了. WPF就是以超吊的binding,com ...

  3. WPF MVVM 架构 Step By Step(3)(把后台代码移到一个类中)

    我觉得大部分开发者应该已经知道怎么去解决这个问题.一般都是把后台代码(GLUE code)移动到一个类库.这个类库用来代表UI的属性和行为.任何代码当被移到一个类库中时都可以被编译成一个DLL,然后可 ...

  4. WPF MVVM架构 EF、WCF、IOC 设计示例经典

    概要 该演示项目利用WPF应用程序构建的MVVM架构示例, 运用了Unity容器接口注入, MVVM的经典设计, 后台利用的EF+WCF. 后台实现: 从数据库生成的emdx 结合上下文进行数据交互, ...

  5. WPF MVVM 架构 Step By Step(2)(简单的三层架构示例及粘合代码GLUE code)

    我们第一步就是去了解三层架构和问题然后去看MVVM是怎么去解决这些问题的. 现在,感觉和事实是完全不同的两个东西.当你看到三层架构的框图的时候,你会觉得每层的职责被分配的很好.但是当你你真的去写代码的 ...

  6. WPF MVVM 架构 Step By Step(1)(介绍)

    生命就是我们从孩子开始,经过不断的学习成为成熟的成年人的进化过程.这和软件的架构有着异曲同工之妙,我们从基础的架构开始,随着需求和环境的变化不断的进化. 如果你去问任何一个.net开发者,什么是最基础 ...

  7. C# WPF - MVVM实现OPC Client管理系统

    前言 本文主要讲解采用WPF MVVM模式设计OPC Client的过程,算作对于WPF MVVM架构的学习记录吧!不足之处请不吝赐教,感谢! 涉及知识点 C#基础 Xaml基础 命令.通知和数据绑定 ...

  8. WPF Step By Step 系列-Prism框架在项目中使用

    WPF Step By Step 系列-Prism框架在项目中使用 回顾 上一篇,我们介绍了关于控件模板的用法,本节我们将继续说明WPF更加实用的内容,在大型的项目中如何使用Prism框架,并给予Pr ...

  9. WPF Step By Step 系列 - 开篇 ·

    WPF Step By Step 系列 - 开篇 公司最近要去我去整理出一个完整的WPF培训的教程,我刚好将自己学习WPF的过程和经验总结整理成笔记的方式来讲述,这里就不按照书上面的东西来说了,书本上 ...

随机推荐

  1. uoj#228 基础数据结构练习题

    题面:http://uoj.ac/problem/228 正解:线段树. 我们可以发现,开根号时一个区间中的数总是趋近相等.判断一个区间的数是否相等,只要判断最大值和最小值是否相等就行了.如果这个区间 ...

  2. xmlplus 组件设计系列之十 - 网格(DataGrid)

    这一章我们要实现是一个网格组件,该组件除了最基本的数据展示功能外,还提供排序以及数据过滤功能. 数据源 为了测试我们即将编写好网格组件,我们采用如下格式的数据源.此数据源包含两部分的内容,分别是表头数 ...

  3. Facebook 宣布开源Python重写后的OnlineSchemaChange

    本文会简要介绍,OnlineSchemaChange在经历从PHP到Python重写后的改进和变化 文章欢迎转载,但转载时请保留本段文字,并置于文章的顶部 作者:卢钧轶(cenalulu) 本文原文地 ...

  4. PXC5.7集群部署

    PXC三节点安装: node1:10.157.26.132 node2:10.157.26.133 node3:10.157.26.134   配置服务器ssh登录无密码验证 ssh-keygen实现 ...

  5. grep与正则表达式

    grep的作用:文本搜索工具,根据用户指定的"模式"对目标文件逐行进行匹配检查:打印匹配到的行. 模式:正则表达式编写的过滤条件. 正则表达式(REGEXP):由一类特殊字符及文本 ...

  6. angular.js的表格指令

    html div.col-sm-12 table.table.table-bordered.table-condensed.table-hover.table-striped.dataTable.no ...

  7. ng-option

    select 是 AngularJS 预设的一组directive.下面是其官网api doc给出的用法:AngularJS:select 大意是,select中的ngOption可以采用和ngRep ...

  8. 使用NetronGraphLib类库开发Qfd质量屋编制工具

    前言 可执行文件下载 QfdHouse-exe.zip 因项目需要做了一个质量功能配置(Quality Function Deployment 简称Qfd)的质量屋编制工具软件,本软件是在发布一个免费 ...

  9. Ubuntu怎样进行自由截图操作

    全屏截图 1. 很简单,键盘上右上角都有一个 Print Screen按键,敲一下,全屏截图操作完成. 自由截图 1. 此种方式很简单,打开系统设置->键盘,进入shortcuts选项 2. 点 ...

  10. 最简单 iText 的 PDF 生成方案(含中文解决方案)HTML 转为 PDF

    转自:http://my.oschina.net/sanji/blog/277704 最近正好项目有用到 ITEXT ,在网络上搜索了一番,发现了很多方案,但是感觉对于一般开发来说都太复杂了,本文提供 ...