1、概述

1.1 WPF C# 命令的本质

命令是 WPF 中的输入机制,它提供的输入处理比设备输入具有更高的语义级别。 例如,在许多应用程序中都能找到的“复制”、“剪切”和“粘贴”操作就是命令。

WPF 中的命令是通过实现 ICommand 接口创建的。 ICommand 的 WPF 实现是 RoutedCommand 类,这是WPF C# 命令的本质。

1.2 WPF C# 命令的机制

1.2.1 编程范围

ICommand 公开两个方法(Execute 及 CanExecute)和一个事件(CanExecuteChanged)。

Execute 执行与命令关联的操作。

CanExecute 确定是否可以在当前命令目标上执行命令。

如果集中管理命令操作的命令管理器检测到命令源中发生了更改,此更改可能使得已引发但尚未由命令绑定执行的命令无效,则将引发 CanExecuteChanged

1.2.2 输入源

WPF 中的主要输入源是鼠标、键盘、墨迹和路由命令。 更加面向设备的输入使用路由事件( RoutedEvent )来通知应用程序页中的对象已发生了输入事件。无论何种输入源, RoutedCommand 没有不同。

1.2.3 应用程序逻辑

RoutedCommand 的 Execute 和 CanExecute 方法不包含命令的应用程序逻辑,而是引发这样的路由事件:沿元素树以隧道和冒泡形式传递,直到遇到具有 CommandBinding 的对象。CommandBinding 包含这些事件的处理程序,执行此命令的就是这些处理程序。( 有关 WPF 中的事件路由的更多信息,请参见路由事件概述。)

1.2.4 命令引发路由事件

RoutedCommand 上的 Execute 方法在命令目标上引发 PreviewExecuted 和 Executed 事件。

RoutedCommand 上的 CanExecute 方法在命令目标上引发 CanExecute 和PreviewCanExecute 事件。

这些事件沿元素树以隧道和冒泡形式传递,直到遇到具有该特定命令的 CommandBinding 的对象。

1.3、WPF C# 命令分类

WPF 通过命令类库提供一组预定义命令。如果命令库类中的命令不满足您的需要,则您可以创建自己的命令。

1.3.1 内置命令库

WPF 提供一组预定义命令库。 命令库包含以下类:ApplicationCommandsNavigationCommandsMediaCommandsEditingCommands 以及 ComponentCommands

这些类提供了一组常用的路由命令.诸如 CutBrowseBackBrowseForwardPlayStop 和 Pause 等命令。

这些命令仅包含 RoutedCommand 对象,而不包含命令的实现逻辑。 实现逻辑由在其上执行命令的对象负责。

命令库中的许多命令都包括一组默认输入绑定。 例如,如果您指定应用程序处理复制命令,则会自动获得键盘绑定“Ctrl+C”。您还会获得其他输入设备(如 Tablet PC 钢笔笔势和语音信息)的绑定。

当您使用 XAML 引用不同的命令库中的命令时,通常可以忽略公开静态命令属性的库类的类名。 通常,命令名称作为字符串是明确的,并且存在用于提供命令的逻辑分组的所属类型,但是这些类型对于消除歧义并不是必需的。 例如,您可以指定 Command="Cut",而不必指定更详细的 Command="ApplicationCommands.Cut"。 这是一种内置于命令的 WPF XAML 处理器中的便利机制(更准确地说,它是 WPF XAML 处理器在加载时引用的 ICommand 的类型转换器行为)。

1.3.2 创建自定义命令

如果命令库类中的命令不满足您的需要,则您可以创建自己的命令。

有两种方法可创建自定义命令。 第一种是从头开始,并实现 ICommand 接口。 另一种方法,也是更常用的方法,是创建RoutedCommand 或 RoutedUICommand

有关创建自定义 RoutedCommand 的示例,请参见 Create a Custom RoutedCommand Sample(创建自定义 RoutedCommand 示例)。

1.4、WPF C# 命令的用途

命令有若干用途。

1.4.1 将语义以及调用命令的对象与执行命令的逻辑分离

第一个用途是将语义以及调用命令的对象与执行命令的逻辑分离开来。 这使得多个完全不同的源可以调用相同的命令逻辑,并使得可以针对不同的目标对命令逻辑进行自定义。 例如,在许多应用程序中都能找到的编辑操作“复制”、“剪切”和“粘贴”都可使用不同的用户操作进行调用(如果这些操作是使用命令实现的)。 应用程序可能允许用户通过单击按钮、选择菜单项或使用组合键(例如 Ctrl+X)剪切所选的对象或文本。 通过使用命令,您可以将各种类型的用户操作绑定到同一逻辑。

1.4.2 操作是否可用

命令的另一个用途是指示操作是否可用。 仍然以剪切对象或文本作为示例,该操作只有在选择了某些内容时才有意义。 如果用户尝试在没有选择任何内容的情况下剪切对象或文本,则不会发生任何操作。 为了向用户指明这一点,许多应用程序都会禁用按钮和菜单项,以使用户了解是否能够执行某项操作。 命令可通过实现 CanExecute 方法来指出操作是否可以执行。 按钮可以订阅CanExecuteChanged 事件,并且,如果 CanExecute 返回 false,则可以禁用按钮,或者,如果 CanExecute 返回 true,则可以启用按钮。

1.4.3 根据目标的类型采取相应的操作

命令的语义在应用程序和类之间可能是一致的,但是操作的逻辑是所作用于的特定对象所特有的。 Ctrl+X 组合键在文本类、图像类以及 Web 浏览器中调用“剪切”命令,但用于执行“剪切”操作的实际逻辑是由执行剪切的应用程序定义的。 RoutedCommand 使客户端能够实现逻辑。 文本对象可以将所选文本剪切到剪贴板中,而图像对象则可以剪切所选图像。 当应用程序处理Executed 事件时,它将能访问命令的目标,并根据目标的类型采取相应的操作。

2、使用WPF 命令

2.1 WPF 命令中的四个主要概念

WPF 中的路由命令模型可以分为四个主要概念:命令、命令源、命令目标以及命令绑定:

  • 命令:是要执行的操作。

  • 命令源:是调用命令的对象。

  • 命令目标:是在其上执行命令的对象。

  • 命令绑定:是将命令逻辑映射到命令的对象。

参见下面的示例。其中,Paste 命令是命令,MenuItem 是命令源,TextBox 是命令目标,命令绑定由 TextBox 控件提供。

值得注意的是,CommandBinding 并不总是由充当命令目标类的控件提供。 非常常见的情况是,CommandBinding 必须由应用程序开发人员创建,或者 CommandBinding 可能附加到命令目标的上级。

2.2 WPF 中的简单命令示例

在 WPF 中使用命令的最简单方法是从某个命令库类中使用预定义的 RoutedCommand;使用对处理此命令具有固有支持的控件;以及使用对调用命令具有固有支持的控件。

Paste 命令是ApplicationCommands 类中的预定义命令之一。 TextBox 控件具有处理 Paste 命令的内置逻辑。 MenuItem 类具有对调用命令的固有支持。下面的示例演示如何设置 MenuItem,以便单击该菜单项时,将对 TextBox 调用 Paste 命令(假定该 TextBox 具有键盘焦点)。

XAML

<StackPanel>
<Menu>
<MenuItem Command="ApplicationCommands.Paste" />
</Menu>
<TextBox />
</StackPanel>
C#

// Creating the UI objects
StackPanel mainStackPanel = new StackPanel();
TextBox pasteTextBox = new TextBox();
Menu stackPanelMenu = new Menu();
MenuItem pasteMenuItem = new MenuItem(); // Adding objects to the panel and the menu
stackPanelMenu.Items.Add(pasteMenuItem);
mainStackPanel.Children.Add(stackPanelMenu);
mainStackPanel.Children.Add(pasteTextBox); // Setting the command to the Paste command
pasteMenuItem.Command = ApplicationCommands.Paste; // Setting the command target to the TextBox
pasteMenuItem.CommandTarget = pasteTextBox;

2.3 编程设计

2.3.1 命令

如前述所述,WPF 中的命令是通过实现 ICommand 接口创建的。 ICommand 公开两个方法(Execute 及 CanExecute)和一个事件(CanExecuteChanged)。 Execute 执行与命令关联的操作。CanExecute 确定是否可以在当前命令目标上执行命令。 如果集中管理命令操作的命令管理器检测到命令源中发生了更改,此更改可能使得已引发但尚未由命令绑定执行的命令无效,则将引发 CanExecuteChanged

RoutedCommand 上的 Execute 方法在命令目标上引发 PreviewExecuted 和 Executed 事件。 RoutedCommand 上的 CanExecute 方法在命令目标上引发 CanExecute 和PreviewCanExecute 事件。 这些事件沿元素树以隧道和冒泡形式传递,直到遇到具有该特定命令的 CommandBinding 的对象。

2.3.2 命令源

命令源是调用命令的对象。 例如,MenuItemButton 和 KeyGesture 就是命令源。

WPF 中的命令源通常实现 ICommandSource 接口。

ICommandSource 公开三个属性:CommandCommandTarget 和 CommandParameter

实现 ICommandSource 的 WPF 类包括:ButtonBaseMenuItemHyperlink 以及 InputBinding

ButtonBase 、MenuItem 和 Hyperlink 在被单击时调用命令,InputBinding 在与之关联的 InputGesture 执行时调用命令。

2.3.2.1 举例: ContextMenu 中的 MenuItem 用作 Properties 命令的命令源

下面的示例演示如何将 ContextMenu 中的 MenuItem 用作 Properties 命令的命令源。

XAML

<StackPanel>
<StackPanel.ContextMenu>
<ContextMenu>
<MenuItem Command="ApplicationCommands.Properties" />
</ContextMenu>
</StackPanel.ContextMenu>
</StackPanel>
C#

StackPanel cmdSourcePanel = new StackPanel();
ContextMenu cmdSourceContextMenu = new ContextMenu();
MenuItem cmdSourceMenuItem = new MenuItem(); // Add ContextMenu to the StackPanel.
cmdSourcePanel.ContextMenu = cmdSourceContextMenu;
cmdSourcePanel.ContextMenu.Items.Add(cmdSourceMenuItem); // Associate Command with MenuItem.
cmdSourceMenuItem.Command = ApplicationCommands.Properties;

通常,命令源会侦听 CanExecuteChanged 事件。 此事件通知命令源,在当前命令目标上执行命令的能力可能已更改。 命令源可以通过使用 CanExecute 方法来查询 RoutedCommand 的当前状态。 之后,如果命令无法执行,则命令源可以禁用其自身。 这种情况的一个示例是:当无法执行命令时,MenuItem 会将自己显示为灰色。

2.3.2.2 举例: InputGesture 作命令源

可以将 InputGesture 用作命令源。 WPF 中两种类型的输入笔势是 KeyGesture 和 MouseGesture。 可以将 KeyGesture 视为键盘快捷方式,如 Ctrl+C。 KeyGesture 由一个 Key 和一组ModifierKeys 组成。 MouseGesture 由一个 MouseAction 和一组可选的 ModifierKeys 组成。

为了使 InputGesture 充当命令源,必须将它与一个命令关联。 有几种方法可实现此目的。 一种方法是使用 InputBinding

下面的示例演示如何在 KeyGesture 与 RoutedCommand 之间创建一个 KeyBinding

XAML

<Window.InputBindings>
<KeyBinding Key="B"
Modifiers="Control"
Command="ApplicationCommands.Open" />
</Window.InputBindings>
C#

KeyGesture OpenKeyGesture = new KeyGesture(
Key.B,
ModifierKeys.Control); KeyBinding OpenCmdKeybinding = new KeyBinding(
ApplicationCommands.Open,
OpenKeyGesture); this.InputBindings.Add(OpenCmdKeybinding);

2.3.2.3  InputGesture 与 RoutedCommand 关联

将 InputGesture 与 RoutedCommand 关联的另一种方法是将 InputGesture 添加到 RoutedCommand 的 InputGestureCollection

下面的示例演示如何将一个 KeyGesture 添加到 RoutedCommand 的 InputGestureCollection

WPF C# 命令的运行机制

命令源

命令源是调用命令的对象。 例如,MenuItemButton 和 KeyGesture 就是命令源。

WPF 中的命令源通常实现 ICommandSource 接口。

ICommandSource 公开三个属性:CommandCommandTarget 和 CommandParameter

实现 ICommandSource 的 WPF 类包括:ButtonBaseMenuItemHyperlink 以及 InputBinding。 ButtonBase 、MenuItem 和 Hyperlink 在被单击时调用命令,InputBinding 在与之关联的 InputGesture 执行时调用命令。

WPF C# 命令的运行机制的更多相关文章

  1. 8、WPF体系架构和运行机制

    体系架构:http://msdn.microsoft.com/zh-cn/library/ms750441.aspx 运行机制:http://www.cnblogs.com/leep2007/arch ...

  2. Java学习系列(一)Java的运行机制、JDK的安装配置及常用命令详解

    俗话说:“十五的月亮十六圆”.那学习是不是也是如此呢?如果把月亮看成是我们的愿望,那十五便是我们所处的“高原期”,坚持迈过这个坎,我相信你的愿望终究会现实的.记得马云曾说:今天很残酷,明天更残酷,后天 ...

  3. (十三)Maven插件解析运行机制

    这里给大家详细说一下Maven的运行机制,让大家不仅知其然,更知其所以然. 1.插件保存在哪里? 与我们所依赖的构件一样,插件也是基于坐标保存在我们的Maven仓库当中的.在用到插件的时候会先从本地仓 ...

  4. Windows程序内部运行机制 转自http://www.cnblogs.com/zhili/p/WinMain.html

    一.引言 要想熟练掌握Windows应用程序的开发,首先需要理解Windows平台下程序运行的内部机制,然而在.NET平台下,创建一个Windows桌面程序,只需要简单地选择Windows窗体应用程序 ...

  5. PHP的运行机制与原理(底层) [转]

    说到php的运行机制还要先给大家介绍php的模块,PHP总共有三个模块:内核.Zend引擎.以及扩展层:PHP内核用来处理请求.文件流.错误处理等相关操作:Zend引擎(ZE)用以将源文件转换成机器语 ...

  6. Chrome扩展开发之二——Chrome扩展中脚本的运行机制和通信方式

    目录: 0.Chrome扩展开发(Gmail附件管理助手)系列之〇——概述 1.Chrome扩展开发之一——Chrome扩展的文件结构 2.Chrome扩展开发之二——Chrome扩展中脚本的运行机制 ...

  7. 深入浅出话VC++(1)——Windows程序内部运行机制

    一.引言 要想熟练掌握Windows应用程序的开发,首先需要理解Windows平台下程序运行的内部机制,然而在.NET平台下,创建一个Windows桌面程序,只需要简单地选择Windows窗体应用程序 ...

  8. 基础知识《零》---Java程序运行机制及运行过程

    Java运行机制 Java虚拟机(Java Virtual Machine):Java虚拟机可以理解成一个以字节码为机器指令的CPU:对于不同的运行平台,有不同的虚拟机:Java虚拟机机制屏蔽了底层运 ...

  9. 【Linux下进程机制】从一道面试题谈linux下fork的运行机制

    今天一位朋友去一个不错的外企面试linux开发职位,面试官出了一个如下的题目: 给出如下C程序,在linux下使用gcc编译: #include "stdio.h" #includ ...

随机推荐

  1. 解决 mac 10.14.4 无法 sublime text 3207 安装 Package Control,以及安装第三方包报错 `Package Control There are no packages available for installation`

    下载最新的 sublime text 3207,无法安装 Package Control. 根据官方提示,手动安装 Package Control. 手动安装 Package Control 后,无法 ...

  2. CAP 2.5 版本中的新特性

    前言 首先,恭喜 CAP 已经成为 eShopOnContainers 官方推荐的生产环境可用的 EventBus 之一. 自从上次 CAP 2.4 版本发布 以来,已经过去了几个月的时间,关注的朋友 ...

  3. ASP.NET Aries 高级开发教程:Excel导入之代码编写(番外篇)

    前言: 以许框架提供的导入配置功能,已经能解决95%以上的导入情况,但有些情况总归还是得代码来解决. 本篇介绍与导入相关的代码. 1.前端追加导入时Post的参数: var grid = new AR ...

  4. CSS Modules In Webpack

    1)从形式上看,CSS Modules 是将CSS中的选择器转换为变量,然后在DOM中引用变量来引入样式. 2)从效果上看,CSS Modules 可以将CSS选择器名字转成随机字符串,保证选择器同名 ...

  5. JS定义函数的2种方式以及区别简述(为什么推荐第二种方式)

     无意中看到了阮一峰大神多年前的一篇博客: 12种不宜使用的Javascript语法    看到第9条的时候受到了启发,感觉之前没怎么理解清楚的一些问题好像突然就清晰了,如下图 可能光这样看,有些小伙 ...

  6. Adobe系列产品卸载不干净怎么解决

    相信很多朋友都遇到过Adobe系列的产品卸载不干净这种问题,究竟如何来解决这个难题呢? Adobe产品在安装的过程中都会自带卸载程序,因此,小编建议各位不要用其他的卸载清理软件来卸载,这样往往会导致卸 ...

  7. 接口自动化:HttpClient + TestNG + Java(二) - 第一个接口测试:get请求

    在上一篇中,我们搭建好了HttpClient + TestNG + Java的自动化接口测试环境,这一篇我们就赶紧开始编写我们的第一个接口测试用例. 本篇会对问题解决的思路进行更详尽的阐述. 2.1 ...

  8. parsing:NLP之chart parser句法分析器

    已迁移到我新博客,阅读体验更佳parsing:NLP之chart parser句法分析器 完整代码实现放在我的github上:click me 一.任务要求 实现一个基于简单英语语法的chart句法分 ...

  9. 痞子衡嵌入式:开启NXP-MCUBootUtility工具的HAB签名功能 - CST(中英双语)

    1 Reason for enabling HAB signature function 为什么要开启HAB签名功能 NXP-MCUBootUtility is a tool designed for ...

  10. DS控件库 DSLed控件呈现滚动字幕效果

    滚动字幕效果在DSled上可以使用偏移来实现,代码如下 运行效果