知识预备

阅读本文,我假定你具备以下知识:

  • C# WPF基础知识
  • 知道WPF的命令

WPF相对WinForm加了一种Command的机制,对用户的操作进行更加灵活的处理,相信很多朋友知道并用过Routed Command,但这不是本文讨论的重点,本文主要讨论在MVVM模式中,用户输入与后台数据的交互所用的Command。

ICommand接口

在WPF中,所有的命令都是基于ICommand接口的,ICommand的接口有三个成员

Execute 方法

这个方法,顾名思义,是在Command被触发时要执行的操作,parameter 是与这个命令绑定相关的Command Parameter

CanExecute 方法

一个Command不是什么时候都可以执行的,比如在登录时,如果没有填写用户名或密码,点击登录按钮是没有意义的,这时应该把Command禁用,在Command Execute之前,命令系统会调用这个方法判断这个命令是否可用。

CanExecuteChanged 事件

当命令的可用状态(availability)发生改变时,比如上面的例子,用户输入了用户名和密码,我们可以通过这个事件通知命令系统,命令系统会重新调用CanExecute方法,更新命令绑定的状态。

RelayCommand

名字由来

和WPF自带的Routed Command不同,在MVVM模式中,当Command把用户的操作传递到ViewModel后,也就完成了他的使命了,因此,我们会在ViewModel中把一个方法和Command关联起来,Command的任务是去调用方法,在这种情况下,Command起着一个中继的作用,RelayCommand这个名字就是这么来的,在Prism 里面,又叫DelegatedCommand。

实现RelayCommand

虽然MVVM Light 里面已经有了一个RelayCommand,但为了了解他的原理,最好的方法就是自己实现一个。

首先我们需要一个接收一个object的Action,用于存放Execute时执行的操作

然后我们需要一个接收一个object,返回值为bool的Func,用于存放CanExecute判断的操作

Command的CanExecute里面,写这样的代码

在Command的Execute里面,执行Execute

然后我们在提供一个方法,用于在命令状态改变时触发 CanExecuteChanged 事件

到此为止,我们已经实现了一个很简陋的RelayCommand,这个Command用于生产环境中时很危险的,但对于我们理解他的原理,已经足够了。

Command Binding 和 Command Parameter

对于Command的绑定非常简单,只需要想数据绑定那样把ViewModel里面的Command绑定到控件的Command属性上就可以了,在这里提一个小建议:在ViewModel中对外暴露的属性用ICommand类型,属性的后台字段用实际的Commad类型,就像这样

因为Command binding需要的只是一个ICommand接口,因此我们不需要对外暴露过多的信息。

上面我们看到,ICommand的Execute和CanExecute方法都有一个object类型的参数,这个参数便是Command Parameter,在绑定命令的时候,可以从控件的CommandParameter属性指定,在CommandParameter更新的时候,Comman的CanExecute会被重新执行(有一些小问题,稍后讲述)

神器Blend SDK

需求是不断变化的,如果哪天我们不是要在按钮被单击时执行操作而是在鼠标移过是执行操作,那WPF自带的Command binding就无能为力了。这时我们就要请出我们的大神——Blend SDK,这里我回答的一个博问作为实例

Windows Phone 的 AppBar

在Windows Phone的开发中,由于App bar是系统部分,不是依赖对象,无法对其Command进行数据绑定,非常不方便。

在这里推荐Allen Lee开发的 AppBarUtils (http://appbarutils.codeplex.com/ ),适用于WP7和WP8,关于这个类库的使用,他的博客有非常详细的教程,这里不再阐述。

你可能会有的疑问

Command parameter 更新时Command状态不改变是怎么回事?

在用MVVM Light时,我发现在非UI线程更新command parameter 时,命令的更新不正确 ,而且我分别在WPF、Sliverlight、WinRT上进行实验,得到三种不同的结果,具体原因我不太说的清,最好的解决办法是使用Dispatcher Helper回到UI线程去更新,用法请看本系列第二篇文章

说不尽的MVVM(4) – 发号施令的Command的更多相关文章

  1. 说不尽的MVVM(1) – Why MVVM

    最近学的一篇课文<说不尽的狗>竟让我有了写<说不尽的MVVM>这一想法,事非亵渎,实出无奈.我在刚学WPF不久时听说有MVVM这种东西,做了下尝试,发现他能给程序的设计带来很大 ...

  2. WPF ContextMenu 在MVVM模式中绑定 Command及使用CommandParameter传参

    原文:WPF ContextMenu 在MVVM模式中绑定 Command及使用CommandParameter传参 ContextMenu无论定义在.cs或.xaml文件中,都不继承父级的DataC ...

  3. 说不尽的MVVM(2) – MVVM初体验

    知识预备 阅读本文,我假定你已经具备以下知识: C#.WPF基础知识 了解Lambda表达式和TPL 对事件驱动模型的了解 知道ICommand接口 发生了什么 某程序员接到一个需求,编写一个媒体渲染 ...

  4. 从PRISM开始学WPF(六)MVVM(二)Command?

    从PRISM开始学WPF(一)WPF? 从PRISM开始学WPF(二)Prism? 从PRISM开始学WPF(三)Prism-Region? 从PRISM开始学WPF(四)Prism-Module? ...

  5. WPF学习08:MVVM 预备知识之COMMAND

    WPF内建的COMMAND是GOF 提出的23种设计模式中,命令模式的实现. 本文是WPF学习07:MVVM 预备知识之数据绑定的后续,将说明实现COMMAND的三个重点:ICommand  Comm ...

  6. 说不尽的MVVM(5) - 消息满天飞

    知识预备 阅读本文,我假定你具备以下知识: C#和WPF基础知识 Lambda表达式 清楚ViewModel的职责 如果我们的程序需要弹出一个MessageBox,我们应该怎么做? 我见过不少人在Vi ...

  7. 说不尽的MVVM(3) – 从通知属性说起

    上篇我们体验了一个从事件处理程序到MVVM程序的转变,在最后也留下了一个问题:RaisePropertyChanged的原理是什么?今天我们来一探究竟. 通过上节做的小例子我们知道,仅仅修改ViewM ...

  8. MVVM中轻松实现Command绑定(三)任意事件的Command

    WPF中不是所有的控件都有Command属性的,如果窗体我需要在ViewModel中处理Loaded事件命令,或者其他事件的命令时,很难都过绑定Command完成,必须要注册依赖属性或事件等,太麻烦了 ...

  9. MVVM中轻松实现Command绑定任意事件的Command

    下面是“银光中国”(不错的WPF或SL网站)WPF学习教程中的一个连接, http://www.silverlightchina.net/html/study/WPF/2011/0715/9034.h ...

随机推荐

  1. 64位Win7下运行ASP+Access网站的方法

    64位Win7下运行ASP+Access网站的方法 近日系统升级为WIN7 64位之后,突然发现原本运行正常的ASP+ACCESS网站无法正常连接数据库. 网上搜索多次,终于解决了问题,总结了几条经验 ...

  2. Correspondence / ˏkɔris'pɔndәns / dictionary10-800.doc

    I have taken courses in office administration, typing,reports and correspondence writing. Correspond ...

  3. AngularJS学习--- 动画操作 (Applying Animations) ngAnimate step 12

    1.切换目录 git checkout step-12 npm start 2.效果图 这里在点击右边的缩略图时,会有一个很明显的从下向上的动画过程. 3.代码实现: step11和step12之间的 ...

  4. const in C++

    const关键字是C++中常用的类型修饰符,用法非常灵活,使用const将大大改善程序的健壮性. const的作用 1.  定义const常量: 比如: const int Max = 100; 2. ...

  5. linux links and lynx

    接下来,说一下links 和 lynx 的一些基本操作,首先你,需要安装这俩个软件 yum install links yum install lynx links links的功能键 一些常见功能按 ...

  6. andorid SQLite数据库创建文件

    package com.hanqi.application3; import android.content.ContentValues; import android.database.sqlite ...

  7. quartus使用笔记

    quartus中默认顶层文件名与工程名相同,或自行设置顶层文件:project->set as top-leval entity 顶层模块名要与工程名相同 RTL是编译后的结果,并没有与实际的硬 ...

  8. OpenWRT连接OPENVPN的教程

    这是相当基本没有任何web界面,只是几个命令如何运行OpenWRT的 OpenVPN的例子. OpenWRT的设置更复杂,所以这个教程仅供爱好者和经验的用户使用参考. 本教程假定您有OpenWRT的安 ...

  9. Okhttp https

    1. 绕过CA证书,不建议使用 private void ingoreCA() throws NoSuchAlgorithmException, KeyManagementException { SS ...

  10. php pdo预处理语句与存储过程

    很多更成熟的数据库都支持预处理语句的概念.什么是预处理语句?可以把它看作是想要运行的 SQL 的一种编译过的模板,它可以使用变量参数进行定制.预处理语句可以带来两大好处: 1.查询仅需解析(或预处理) ...