WPF命令模型由许多可变的部分组成。总之,它们都具有如下4个重要元素:

  •   命令:命令表示应用程序任务,并且跟踪任务是否能够被执行。然而,命令实际上不包含执行应用程序任务的代码。
  •   命令绑定:每个命令绑定针对用户界面的具体区域,将命令连接到相关的应用程序逻辑。这种分解的设计是非常重要的,因为单个命令可用于应用程序中的多个地方,并且在每个地方具有不同的意义。为处理这一问题,需要将同一命令与不同的命令绑定。
  •   命令源:命令源触发命令。例如,MenuItem和Button都是命令源。单击它们都会执行绑定命令。
  •   命令目标:命令目标是在其中执行命令的元素。例如,Paste命令可在TextBox控件中插入文本,而OpenFile命令可在DocumentViewer中打开文档。根据命令的本质,目标可能很重要,也可能不重要。

一、ICommand接口

  WPF命令模型的核心是System.Windows.Input.ICommand接口,该接口定义了命令的工作原理。该接口包含两个方法和一个事件:

public interface ICommand
{
void Execute(object parameter);
bool CanExecute(object parameter); event EventHandler CanExecuteChanged;
}

  在一个简单实现中,Execute()方法将包含应用程序任务逻辑(例如,打印文档)。然而,正如下一节中将看到,WPF的实现更复杂。它使用Execute()方法引发一个更复杂的过程,该过程最终触发在应用程序其他地方处理的事件。通过这种方式可以使用预先准备好的命令类,并插入自己的逻辑。还可以灵活地再几个不同地方使用同一个命令(如Print命令)。

  CanExecute()方法返回命令的状态——如果命令可用,就返回true;如果不可用,就返回false。Execute()和CanExecute()方法都接受一个附加的参数对象,可使用该对象传递所需的任何附加信息。

  最初,当命令状态改变时引发CanExecuteChanged事件。对于使用命令的任何事件,这是指示信号,表示它们应当调用CanExecute()方法检查命令的状态。通过使用该事件,当命令可用时,命令源(如Button或MenuItem)可自动启用自身;当命令不可用时,禁用自身。

二、RoutedCommand类

  当创建自己的命令时,不会直接实现ICommand接口;而是使用System.Windows.Input.RoutedCommand类,该类自动实现了ICommand接口。RoutedCommand类是WPF中唯一实现了ICommand接口的类。换句话说,所有WPF命令都是RoutedCommand类及其派生类的实例。

  在WPF命令模型背后的一个重要概念是,RoutedCommand类不包含任何应用程序逻辑,而只代表命令,这意味着各个RoutedCommand对象具有相同的功能。

  RoutedCommand类为事件冒泡和隧道添加了一些额外的基础结构。鉴于ICommand接口封装了命令的思想——可被触发的动作并可被启用或禁用——RoutedCommand类对命令进行了修改,使命令可在WPF元素层次结构中冒泡,以便获得正确的事件处理程序。

  为支持路由事件,RoutedCommand类私有地实现了ICommand接口,并添加了ICommand接口方法的一些不同版本。最明显的变化是,Execute()和CanExecute()方法使用了一个额外参数。下面的新的签名:

public void Execute(object parameter,IInputElement target)
{
//...
} public void CanExecute(object parameter,IInputElement target)
{
//...
}

  参数target是开始处理事件的元素。事件从target元素开始,然后冒泡至高层的容器,直到应用程序为了执行合适的任务而处理了事件(为了处理Executed事件,元素还需要借助于另一个类——CommandBinding类的帮助)。

  除上面的修改外,RoutedCommand类还引入了三个属性:命令名称(Name属性)、包含命令的类(OwnerType)以及任何可用于触发命令的按键或鼠标操作(位于InputGestures集合中)。

三、RoutedUICommand类

  在程序中处理的大部分命令不是RoutedCommand对象,而是RoutedUICommand类的实例,RoutedUICommand类继承自RoutedCommand类(实际上,WPF提供的所有预先构建好的命令都是RoutedUICommand对象)。

  RoutedUICommand类用于具有文本的命令,这些文本显示在用户界面中的某些地方(例如菜单项文本、工具栏按钮的工具栏提示)。RoutedUICommand类只添加了Text属性,该属性是为命令显示的文本。

  为命令定义命令文本(而不是直接在控件上定义文本)的优点是可在某个位置执行本地化。但如果命令文本永远不会在用户界面的任何地方显示,那么RoutedUICommand类和RoutedCommand类是等效的。

四、命令库

  WPF设计者认识到,每个应用程序可能都有大量命令,并且对于许多不同的应用程序,很多命令时通用的,例如,所有基于文档的应用程序都有他们自己版本的New、Open以及Save命令。为减少创建这些命令所需的工作,WPF提供了基本命令库,基本命令库中保存的命令超过100条。这些命令通过以下5个专门的静态类的属性提供:

  •   ApplicationCommands:该类提供了通用命令,包括剪贴板命令(如Copy、Cut和Paste)以及文档命令(如New、Open、Save、SaveAs和Print等)。
  •   NavigationCommands:该类提供了用于导航的命令,包括为基于页面的应用程序设计的一些命令(如BrowseBack、BrowSeForward和NextPage),以及其他适合于基于文档的应用程序的命令(如IncreaseZoom和Refresh).
  •   EditingCommands:该类提供了许多重要的文档编辑命令,包括用于移动的命令(MoveToLineEnd、MoveLeftByWord和MoveUpByPage等),选择内容的命令(SelectToLineEnd、SelectLeftByWord),以及改变格式的命令(ToggleBold和ToggleUnderLine)。
  •   ComponentCommands:该类提供了由用户界面组件使用的命令,包括用于移动和选择内容的命令,这些命令和EditingCommands类中的一些命令类似(甚至完全相同)。
  •   MediaCommands:该类提供了一组用于处理多媒体的命令(如Play、Pause、NextTrack以及IncreaseVolume).

  ApplicationCommands类提供了一组基本命令,在所有类别的应用程序中都经常会用到这些命令,所以在此简单介绍一下。下面列出了所有这些命令。

New Copy SelectAll
Open Cut Stop
Save Paste ContextMenu

SaveAs

Delete CorrectionList
Close Undo Properties
Print Redo Help
PrintPreview Find  
CancelPrint Replace  

  例如,ApplicationCommands.Open是提供RoutedUICommand对象的静态属性,该对象表示应用程序中的Open命令。因为ApplicationCommands.Open是静态属性,所以在整个应用程序中只有一个Open命令实例。然而,根据命令源的不同(换句话说,是在用户界面的什么地方触发的该命令),可采用不同的处理方式。

  每个命令的RoutedUICommand.Text属性和名称是相互匹配的,指示在单词之间添加了空格。例如,ApplicationCommands.SelectedAll命令的文本时SelecteAll(Name属性使用相同的没有空格的文本)。因为Open命令时ApplicationCommands类的静态属性,所以RoutedUICommand.OwnerType属性返回ApplicationCommands类的类型对象。

  这些单独的命令对象仅时一些标志起,不具有实际功能。然而,许多命令对象都有一个额外的特征:默认输入绑定。例如,ApplicationCommands.Open命令被映射到Ctrl+O快捷键。只要将命令绑定到命令源,并为窗口添加命令源,这个快捷键就会被激活,即使没有在用户界面的任何地方显示该命令也同样如此。

【WPF学习】第三十一章 WPF命令模型的更多相关文章

  1. 风炫安全web安全学习第三十一节课 命令执行以及代码执行演示

    风炫安全web安全学习第三十一节课 命令执行以及代码执行演示 参考: http://blog.evalshell.com/2020/12/20/风炫安全web安全学习第三十一节课-命令执行以及代/

  2. 【WPF学习】第二十一章 特殊容器

    内容控件不仅包括基本控件,如标签.按钮以及工具提示:它们还包含特殊容器,这些容器可用于构造用户界面中比较大的部分区域. 首先介绍ScrollViewer控件,该控件直接继承自ContentContro ...

  3. WPF自学入门(十一)WPF MVVM模式Command命令 WPF自学入门(十)WPF MVVM简单介绍

    WPF自学入门(十一)WPF MVVM模式Command命令   在WPF自学入门(十)WPF MVVM简单介绍中的示例似乎运行起来没有什么问题,也可以进行更新.但是这并不是我们使用MVVM的正确方式 ...

  4. C#高级编程(第六版)学习:第三十一章:Windows窗体

    第三十一章 Windows窗体 创建Windows窗体应用程序 在文本编辑器中输入: /* * form.cs * a simple windows form * */ using System; u ...

  5. “全栈2019”Java多线程第三十一章:中断正在等待显式锁的线程

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  6. “全栈2019”Java第三十一章:二维数组和多维数组详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  7. Gradle 1.12用户指南翻译——第三十一章. FindBugs 插件

    其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Github上的地址: https://g ...

  8. angular学习笔记(三十一)-$location(2)

    之前已经介绍了$location服务的基本用法:angular学习笔记(三十一)-$location(1). 这篇是上一篇的进阶,介绍$location的配置,兼容各版本浏览器,等. *注意,这里介绍 ...

  9. angular学习笔记(三十一)-$location(1)

    本篇介绍angular中的$location服务的基本用法,下一篇介绍它的复杂的用法. $location服务的主要作用是用于获取当前url以及改变当前的url,并且存入历史记录. 一. 获取url的 ...

随机推荐

  1. iptables详细参数讲解

    table 表 --> chain 链 --->rule 规则Commands:Either long or short options are allowed. --append -A ...

  2. 【题解】PKUWC2018简要题解

    [题解]PKUWC2018简要题解 Minimax 定义结点x的权值为: 1.若x没有子结点,那么它的权值会在输入里给出,保证这类点中每个结点的权值互不相同. 2.若x有子结点,那么它的权值有p的概率 ...

  3. Web基础了解版11-Ajax-JSON

    Ajax AJAX即“Asynchronous Javascript And XML”:是,不发生页面跳转.异步请求载入内容并改写局部页面内容的技术. 也可以简单的理解为通过JS向服务器发送请求.   ...

  4. Session是怎么实现的?存储在哪里?

    为什么有session? 首先大家知道,http协议是无状态的,即你连续访问某个网页100次和访问1次对服务器来说是没有区别对待的,因为它记不住你. 那么,在一些场合,确实需要服务器记住当前用户怎么办 ...

  5. bash的默认组合键

    组合键 组合按键 执行结果 Ctrl+C 终止目前的命令 Ctrl+D 输入结束(EOF),例如邮件结束的时候 Ctrl+M 就是Enter啦! Ctrl+S 暂停屏幕输出 Ctrl+Q 恢复屏幕输出 ...

  6. docker启动报错 (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport

    今天修改完docker宿主机的防火墙文件 vim /etc/sysconfig/iptables 停止容器再启动时 报如下错误 (iptables failed: iptables --wait -t ...

  7. Java操作Jxl实现数据交互。三部曲——《第三篇》

    Java操作Jxl实现上传文本文件实现转PDF格式在线预览. 本文实现背景Web项目:前台用的框架是Easyui+Bootstrap结合使用,需要引入相应的Js.Css文件.页面:Jsp.拦截请求:S ...

  8. js正则定义支付宝账号、手机号、邮箱

    一.支付宝账号:可以只输入数字.字母.字母(数字)+数字(字母),其中只字母中可以含有@._或者.也可以三者都可以包含并且可以在任意位置,限制:小于等于30位(可根据需求自定义范围): let  zh ...

  9. cogs 1583. [POJ 3237] 树的维护 树链剖分套线段树

    1583. [POJ 3237] 树的维护 ★★★★   输入文件:maintaintree.in   输出文件:maintaintree.out   简单对比时间限制:5 s   内存限制:128 ...

  10. php获取本年、本月、本周时间戳和日期格式

    时间戳格式: //获取今日开始时间戳和结束时间戳 $beginToday=mktime(0,0,0,date('m'),date('d'),date('Y')); $endToday=mktime(0 ...