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 }

两个核心方法

  1. Execute() 
    点击按钮时真正做事的方法。
  2. 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 }

三个核心属性

  1. Command → 要执行哪个命令
  2. CommandParameter → 命令参数
  3. CommandTarget → 命令在哪个元素上执行
一句话:
ICommandSource = 按钮这类 “能点、能触发命令” 的控件。

3. 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 个概念一句话记住

  1. ICommand → 命令的标准(必须有 Execute/CanExecute)
  2. ICommandSource → 能触发命令的控件(Button、MenuItem)
  3. CommandTarget → 命令发给谁执行
  4. CommandBinding → 命令绑定到后台代码
  5. RoutedCommand → 会向上冒泡的路由命令
  6. CommandRepository → 全局静态命令仓库(统一管理)

完整流程(终极版)

1 Button(ICommandSource)
2    → 发出 RoutedCommand
3    → 通过 CommandTarget 指定目标
4    → 向上路由冒泡
5    → 找到 CommandBinding
6    → 执行 Execute / CanExecute

 

posted on 2026-03-25 15:23  工业搬砖猿Lee  阅读(27)  评论(0)    收藏  举报