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. DOCKER学习_008:Docker容器的运行最佳实践

    一 容器分类 容器按用途大致可分为两类: 服务类容器,如 web server. database等 工具类容器,如cur容器, Iredis-cli容器 通常而言,服务类容器需要长期运行,所以使用 ...

  2. 003 ansible部署ceph集群

    介绍:在上一次的deploy部署ceph,虽然出了结果,最后的结果并没有满足最初的目的,现在尝试使用ansible部署一遍,看是否会有问题 一.环境准备 ceph1充当部署节点,ceph2,ceph3 ...

  3. 【温故知新】Java web 开发(一) 新建项目

    简述本文写作目的:本文主要用于回忆基础 java web 项目的搭建,在不使用 Spring 等框架的前提下,单纯使用 jsp 和 servlet 完成. 1. 新建 maven 项目,不使用 arc ...

  4. appium整个环境安装详细教程(重要)

    环境依赖 Node.js Appium Appium-desktop Appium-doctor Appium-Python-Client Python JDK Andriod SDK 以上所需的软件 ...

  5. 02_小程序——onPageScroll 你入坑了吗?

    1:你的 onPageScroll 事件是不是失灵?闲话不多说,直接上代码!!! <!--pages/homePage/testing/testing.wxml--> <view c ...

  6. 文档对象DOM的操作及使用

    Dom对象是什么? DOM对象就是每次你打开浏览器后,进入一个网址时浏览器获取到的HTML文本内容,当浏览器获取到HTML文本内容时,会将其内容以DOM对象的形式缓存到内存中,这时你便可以对DOM对象 ...

  7. Using TFRecords and tf.Example

    -----这篇其实是TensorFlow的官方tutorials,由于没有翻译,笔者姑且翻译一下,用来日后思考.------- 原址:https://www.tensorflow.org/tutori ...

  8. 17.python自定义模块的导入方式

    1.直接用import导入 最后运行main.py可以看到命令行窗口输出了一句:你好,这样就完成了. 2.通过sys模块导入自定义模块的路径path 3.在环境变量中找到自定义模块 这个方法原理就是利 ...

  9. electron-vue 设置cookie

    //设置登录cookie setCookie(name,value){ var Days=30; var exp=new Date(); var date=Math.round(exp.getTime ...

  10. TensorFlow——LinearRegression简单模型代码

    代码函数详解 tf.random.truncated_normal()函数 tf.truncated_normal函数随机生成正态分布的数据,生成的数据是截断的正态分布,截断的标准是2倍的stddev ...