ICommand、ICommandSource、CommandTarget、CommandBinding、RoutedCommand、Command Repository
0. 先给你一张总关系图(一眼看懂)
1 触发控件(Button) 2 ↓(实现 ICommandSource) 3 发出 ICommand(RoutedCommand) 4 ↓ 5 通过 CommandTarget 指定目标 6 ↓ 7 在可视化树上 向上路由(冒泡) 8 ↓ 9 找到 CommandBinding 10 ↓ 11 执行 Execute / CanExecute
所有命令都围绕这 6 个东西运转。
1. ICommand 接口(命令的标准契约)
是什么?
所有命令必须实现的接口,是 WPF 命令的根。
接口定义
1 public interface ICommand 2 { 3 // 执行命令 4 void Execute(object parameter); 5 6 // 命令是否可执行(控制按钮是否可用) 7 bool CanExecute(object parameter); 8 9 // 可执行状态改变时触发 10 event EventHandler CanExecuteChanged; 11 }
两个核心方法
- Execute()
点击按钮时真正做事的方法。 - CanExecute()
返回 true → 按钮可用
返回 false → 按钮灰掉、不可点
作用
定义命令必须具备的功能,不管是系统命令还是自定义命令,都必须遵守它。
2. ICommandSource 接口(命令触发源)
是什么?
能发出命令的控件,都实现了这个接口。
常见控件
- Button
- MenuItem
- CheckBox
- RadioButton
- HyperLink
接口定义
1 public interface ICommandSource 2 { 3 ICommand Command { get; } 4 object CommandParameter { get; } 5 IInputElement CommandTarget { get; } 6 }
三个核心属性
- Command → 要执行哪个命令
- CommandParameter → 命令参数
- CommandTarget → 命令在哪个元素上执行
一句话:
ICommandSource = 按钮这类 “能点、能触发命令” 的控件。
ICommandSource = 按钮这类 “能点、能触发命令” 的控件。
3. CommandTarget(命令目标)
是什么?
命令发给谁去执行。
默认规则
不写 CommandTarget → 命令发给 焦点所在控件
写了 CommandTarget → 命令只发给你指定的元素
写了 CommandTarget → 命令只发给你指定的元素
例子
1 <Button Command="ApplicationCommands.Paste" 2 CommandTarget="{Binding ElementName=txtInput}" />
意思:
点击按钮,让 txtInput 文本框执行粘贴命令
作用
精确控制命令由谁接收,不路由、不冒泡。
4. CommandBinding(命令绑定 = 命令 + 逻辑)
是什么?
把命令和后台代码绑定在一起的桥梁。
没有 CommandBinding → 命令永远不会执行!
结构
1 CommandBinding = 命令 + 执行方法 + 可执行方法
代码示例
1 var binding = new CommandBinding(ApplicationCommands.Save); 2 binding.Executed += Save_Executed; // 执行逻辑 3 binding.CanExecute += Save_CanExecute; // 是否可用 4 5 this.CommandBindings.Add(binding); // 注册到窗口
XAML 写法
1 <Window.CommandBindings> 2 <CommandBinding Command="Save" Executed="Save_Executed" /> 3 </Window.CommandBindings>
作用
告诉 WPF:这个命令来了,由谁处理。
5. RoutedCommand(路由命令 = WPF 默认命令)
是什么?
ICommand 的默认实现,WPF 内置命令全是它。
特点:会沿着可视化树向上冒泡传递!
特点:会沿着可视化树向上冒泡传递!
执行流程(超级重要)
1 按钮发出命令 2 ↓ 3 向上冒泡:Grid → StackPanel → Window 4 ↓ 5 找到第一个 CommandBinding 6 ↓ 7 执行 Executed
系统内置命令都是 RoutedCommand
- ApplicationCommands(新建、打开、保存、打印)
- EditingCommands(剪切、复制、粘贴)
- NavigationCommands(导航)
- MediaCommands(媒体)
自定义路由命令
1 public static class MyCommands 2 { 3 public static RoutedCommand Delete = new RoutedCommand(); 4 }
优点
- 一个命令,多处可绑定
- 自动冒泡,自动找处理者
- 支持快捷键、菜单、按钮统一触发
6. Command Repository(命令仓库 / 静态命令库)
是什么?
把所有命令统一放在一个静态类里,方便全局调用。
企业开发标准写法!
代码示例
1 public static class CommandRepository 2 { 3 // 全局命令 4 public static ICommand Save { get; } = new RoutedCommand(); 5 public static ICommand Delete { get; } = new RoutedCommand(); 6 public static ICommand Query { get; } = new RoutedCommand(); 7 }
XAML 使用
1 <Button Command="{x:Static local:CommandRepository.Save}" />
优点
- 统一管理
- 全局复用
- 便于维护
- MVVM 架构标准
最终总结:6 个概念一句话记住
- ICommand → 命令的标准(必须有 Execute/CanExecute)
- ICommandSource → 能触发命令的控件(Button、MenuItem)
- CommandTarget → 命令发给谁执行
- CommandBinding → 命令绑定到后台代码
- RoutedCommand → 会向上冒泡的路由命令
- CommandRepository → 全局静态命令仓库(统一管理)
完整流程(终极版)
1 Button(ICommandSource) 2 → 发出 RoutedCommand 3 → 通过 CommandTarget 指定目标 4 → 向上路由冒泡 5 → 找到 CommandBinding 6 → 执行 Execute / CanExecute
浙公网安备 33010602011771号