wpf 命令理解
命令包含RouteCommand和CustomCommand类
RouteCommand
通常用于自定义控件,或者入门学习时用
本身仅定义命令标识,必须通过 CommandBinding 关联执行逻辑,以下代码的CommandBinding是后台代码添加的Windows.CommandBinding.Add();
如果不是后台代码,用xaml语言的话
<Window.Resources>
<RoutedUICommand x:Key="PlayCommand" Text="Open"/>
</Window.Resources><Window.CommandBindings>
<CommandBinding Command="{StaticResource PlayCommand}"Executed="CommandBinding_Executed"CanExecute="CommandBinding_CanExecute"/>
</Window.CommandBindings>
后台代码
using System;
using System.Windows;
using System.Windows.Input;// 自定义命令类(使用RoutedCommand实现路由功能)
public static class CustomCommands
{// 声明命令public static readonly RoutedCommand Save = new RoutedCommand("Save", // 命令名称typeof(CustomCommands), // 所属类型new InputGestureCollection // 可选:定义快捷键{new KeyGesture(Key.S, ModifierKeys.Control) // Ctrl+S});public static readonly RoutedCommand Delete = new RoutedCommand("Delete", typeof(CustomCommands),new InputGestureCollection{new KeyGesture(Key.Delete) // Delete键});
}// 命令执行逻辑(通常在ViewModel或代码后台实现)
public class CommandHandler
{// 注册命令绑定public static void RegisterCommandBindings(UIElement element){// 保存命令绑定element.CommandBindings.Add(new CommandBinding(CustomCommands.Save,Save_Executed, // 执行逻辑Save_CanExecute // 能否执行的判断));// 删除命令绑定element.CommandBindings.Add(new CommandBinding(CustomCommands.Delete,Delete_Executed,Delete_CanExecute));}// 保存命令执行private static void Save_Executed(object sender, ExecutedRoutedEventArgs e){// 实际保存逻辑MessageBox.Show("执行保存操作");e.Handled = true;}// 保存命令是否可执行private static void Save_CanExecute(object sender, CanExecuteRoutedEventArgs e){// 这里可以根据条件判断是否允许执行(例如:数据是否已修改)e.CanExecute = true; // 始终允许执行e.Handled = true;}// 删除命令执行private static void Delete_Executed(object sender, ExecutedRoutedEventArgs e){// 实际删除逻辑if (MessageBox.Show("确定要删除吗?", "提示", MessageBoxButton.YesNo) == MessageBoxResult.Yes){MessageBox.Show("执行删除操作");}e.Handled = true;}// 删除命令是否可执行private static void Delete_CanExecute(object sender, CanExecuteRoutedEventArgs e){// 例如:只有选中项存在时才允许删除e.CanExecute = true; // 简化示例,始终允许e.Handled = true;}
}
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Input;// 模拟RoutedCommand的核心实现
public class MyRoutedCommand
{// 命令元数据public string Name { get; }public Type OwnerType { get; }public InputGestureCollection InputGestures { get; }// 构造函数:初始化命令元数据public MyRoutedCommand(string name, Type ownerType, InputGestureCollection inputGestures = null){Name = name;OwnerType = ownerType;InputGestures = inputGestures ?? new InputGestureCollection();}// 执行命令:核心方法public void Execute(object parameter, IInputElement target){if (target == null) return;// 1. 创建命令执行事件参数var args = new ExecutedRoutedEventArgs(this, parameter){Source = target};// 2. 在目标元素上触发路由事件(冒泡)target.RaiseEvent(args);// 3. 如果事件未被处理,继续向上传播(简化逻辑)if (!args.Handled){var parent = VisualTreeHelper.GetParent(target as DependencyObject);if (parent is IInputElement parentElement){Execute(parameter, parentElement); // 递归向上查找处理者}}}// 判断命令是否可执行public bool CanExecute(object parameter, IInputElement target){if (target == null) return false;// 1. 创建可用性判断事件参数var args = new CanExecuteRoutedEventArgs(this, parameter){Source = target,CanExecute = false // 默认不可执行};// 2. 在目标元素上触发路由事件target.RaiseEvent(args);// 3. 如果未找到处理者,继续向上传播if (!args.Handled){var parent = VisualTreeHelper.GetParent(target as DependencyObject);if (parent is IInputElement parentElement){return CanExecute(parameter, parentElement);}}return args.CanExecute;}
}// 配套的路由事件参数(简化版)
public class ExecutedRoutedEventArgs : RoutedEventArgs
{public MyRoutedCommand Command { get; }public object Parameter { get; }public ExecutedRoutedEventArgs(MyRoutedCommand command, object parameter){Command = command;Parameter = parameter;RoutedEvent = CommandManager.ExecutedEvent; // 关联命令系统的执行事件}
}public class CanExecuteRoutedEventArgs : RoutedEventArgs
{public MyRoutedCommand Command { get; }public object Parameter { get; }public bool CanExecute { get; set; }public CanExecuteRoutedEventArgs(MyRoutedCommand command, object parameter){Command = command;Parameter = parameter;RoutedEvent = CommandManager.CanExecuteEvent; // 关联可用性判断事件}
}
CustomCommand类
继承ICommand,命名为RelayCommand或者DelegateCommand
在viewmodel中声明初始化
常用于MVVM开发