WPF C# 命令的运行机制
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 提供一组预定义命令库。 命令库包含以下类:ApplicationCommands、NavigationCommands、MediaCommands、EditingCommands 以及 ComponentCommands。
这些类提供了一组常用的路由命令.诸如 Cut、BrowseBack、BrowseForward、Play、Stop 和 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 命令源
命令源是调用命令的对象。 例如,MenuItem、Button 和 KeyGesture 就是命令源。
WPF 中的命令源通常实现 ICommandSource 接口。
ICommandSource 公开三个属性:Command、CommandTarget 和 CommandParameter:
Command 是在调用命令源时执行的命令。
CommandTarget 是要在其上执行命令的对象。 值得注意的是,在 WPF 中,ICommandSource 上的 CommandTarget 属性只有在 ICommand 是 RoutedCommand 时才适用。 如果在 ICommandSource 上设置了 CommandTarget,而对应的命令不是 RoutedCommand,将会忽略命令目标。 如果未设置 CommandTarget,则具有键盘焦点的元素将是命令目标。
CommandParameter 是用户定义的数据类型,用于将信息传递到实现命令的处理程序。
实现 ICommandSource 的 WPF 类包括:ButtonBase、MenuItem、Hyperlink 以及 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# 命令的运行机制
命令源
命令源是调用命令的对象。 例如,MenuItem、Button 和 KeyGesture 就是命令源。
WPF 中的命令源通常实现 ICommandSource 接口。
ICommandSource 公开三个属性:Command、CommandTarget 和 CommandParameter:
Command 是在调用命令源时执行的命令。
CommandTarget 是要在其上执行命令的对象。 值得注意的是,在 WPF 中,ICommandSource 上的 CommandTarget 属性只有在 ICommand 是 RoutedCommand 时才适用。 如果在 ICommandSource 上设置了 CommandTarget,而对应的命令不是 RoutedCommand,将会忽略命令目标。 如果未设置 CommandTarget,则具有键盘焦点的元素将是命令目标。
CommandParameter 是用户定义的数据类型,用于将信息传递到实现命令的处理程序。
实现 ICommandSource 的 WPF 类包括:ButtonBase、MenuItem、Hyperlink 以及 InputBinding。 ButtonBase 、MenuItem 和 Hyperlink 在被单击时调用命令,InputBinding 在与之关联的 InputGesture 执行时调用命令。
WPF C# 命令的运行机制的更多相关文章
- 8、WPF体系架构和运行机制
体系架构:http://msdn.microsoft.com/zh-cn/library/ms750441.aspx 运行机制:http://www.cnblogs.com/leep2007/arch ...
- Java学习系列(一)Java的运行机制、JDK的安装配置及常用命令详解
俗话说:“十五的月亮十六圆”.那学习是不是也是如此呢?如果把月亮看成是我们的愿望,那十五便是我们所处的“高原期”,坚持迈过这个坎,我相信你的愿望终究会现实的.记得马云曾说:今天很残酷,明天更残酷,后天 ...
- (十三)Maven插件解析运行机制
这里给大家详细说一下Maven的运行机制,让大家不仅知其然,更知其所以然. 1.插件保存在哪里? 与我们所依赖的构件一样,插件也是基于坐标保存在我们的Maven仓库当中的.在用到插件的时候会先从本地仓 ...
- Windows程序内部运行机制 转自http://www.cnblogs.com/zhili/p/WinMain.html
一.引言 要想熟练掌握Windows应用程序的开发,首先需要理解Windows平台下程序运行的内部机制,然而在.NET平台下,创建一个Windows桌面程序,只需要简单地选择Windows窗体应用程序 ...
- PHP的运行机制与原理(底层) [转]
说到php的运行机制还要先给大家介绍php的模块,PHP总共有三个模块:内核.Zend引擎.以及扩展层:PHP内核用来处理请求.文件流.错误处理等相关操作:Zend引擎(ZE)用以将源文件转换成机器语 ...
- Chrome扩展开发之二——Chrome扩展中脚本的运行机制和通信方式
目录: 0.Chrome扩展开发(Gmail附件管理助手)系列之〇——概述 1.Chrome扩展开发之一——Chrome扩展的文件结构 2.Chrome扩展开发之二——Chrome扩展中脚本的运行机制 ...
- 深入浅出话VC++(1)——Windows程序内部运行机制
一.引言 要想熟练掌握Windows应用程序的开发,首先需要理解Windows平台下程序运行的内部机制,然而在.NET平台下,创建一个Windows桌面程序,只需要简单地选择Windows窗体应用程序 ...
- 基础知识《零》---Java程序运行机制及运行过程
Java运行机制 Java虚拟机(Java Virtual Machine):Java虚拟机可以理解成一个以字节码为机器指令的CPU:对于不同的运行平台,有不同的虚拟机:Java虚拟机机制屏蔽了底层运 ...
- 【Linux下进程机制】从一道面试题谈linux下fork的运行机制
今天一位朋友去一个不错的外企面试linux开发职位,面试官出了一个如下的题目: 给出如下C程序,在linux下使用gcc编译: #include "stdio.h" #includ ...
随机推荐
- kafka 幂等生产者及事务(kafka0.11之后版本新特性)
1. 幂等性设计1.1 引入目的生产者重复生产消息.生产者进行retry会产生重试时,会重复产生消息.有了幂等性之后,在进行retry重试时,只会生成一个消息. 1.2 幂等性实现1.2.1 PID ...
- 使用 shell / python 进行sql的excel报表导出
如果要求你进行一个表数据的导出,如果使用shell的话,很容易做到,即执行一下 select 语句就可以拿到返回结果了! 如下: /usr/bin/mysql -u"${username}& ...
- 从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 十四 ║ VUE 计划书 & 我的前后端开发简史
---新内容开始--- 番外 大家周一好呀,又是元气满满的一个周一呀!感谢大家在周一这个着急改Bug的黄金时期,抽出时间来看我的博文哈哈哈,时间真快,已经到第十四篇博文了,也很顺顺(跌跌)利利 (撞撞 ...
- 【Python语言】--Crontab结合Python脚本实现将日志每天写入到文件中
一.前述 实际工作中将Python脚本每天定时写入到日志文件中的使用场景还是蛮多的,有很多种方法可以实现这种效果.本文选择一种方式实现,特将实现细节做如下分享,不当之处烦请指正. 二.具体 1.pyt ...
- 【Netty】(7)---搭建websocket服务器
[Netty](7)---搭建websocket服务器 说明:本篇博客是基于学习某网有关视频教学. 目的:创建一个websocket服务器,获取客户端传来的数据,同时向客户端发送数据 一.服务端 1. ...
- docker~不使用yml批量部署服务
回到目录 有时,我们在进行持续集成环境有时,有时yml环境是没有的,它可能只提供了docker工具,而docker-compose这个大家伙可能不被提供,而这样我们如果希望自动化构建解决方案下所有的项 ...
- Asp.Net Core 轻松学-实现跨平台的自定义Json数据包
前言 在前后端分离的业务开发中,我们总是需要返回各种各样的数据包格式,一个良好的 json 格式数据包是我们一贯奉行的原则,下面就利用 Json.Net 来做一个简单具有跨平台的序列化数据包实 ...
- 【面试】我是如何在面试别人Spring事务时“套路”对方的
“中国最好面试官” 自从上次写了一篇“[面试]我是如何面试别人List相关知识的,深度有点长文”的文章后,有读者专门加我微信,说我是“中国最好面试官”,这个我可受不起呀. 我只是希望把面试当作是一次交 ...
- 初步认识Swiper_前端交互控制神器_滚动3D切换等特效简单制作
前言: 本人在项目的工作中负责研发,页面及交互基本都是交给前端去做的.以前前端写的东西大概都知道,都是一些JS,CSS和HTML等的一些基本控制,都懂!但是今天前端突然做了一个具有特殊效果的DOM:页 ...
- Java 单例(Singleton)模式
一.什么是单例模式: 单例模式是一种确保了一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.被实例化的类称为单例类. 二.单例模式的特点: 单例类只有一个实例. 单例类必须自行创建自己唯一的 ...