WPF的命令绑定机制允许开发者将界面元素的操作与后台业务逻辑分离,避免直接在事件处理方法中编写大量业务代码,提升项目的可维护性和可测试性。ICommand接口是所有WPF命令的基础,所有自定义命令都需要实现这个接口。

ICommand接口核心说明
ICommand接口位于System.Windows.Input命名空间下,定义了命令需要实现的两个核心方法和两个事件,具体定义如下:
- Execute方法:命令被执行时调用的方法,用来编写具体的业务逻辑
- CanExecute方法:用来判断命令当前是否可以执行,返回true表示可以执行,返回false则命令会被禁用
- CanExecuteChanged事件:当命令的可执行状态发生变化时触发,通知界面更新命令的可用状态
自定义基础命令类实现
我们可以创建一个通用的RelayCommand类来实现ICommand接口,避免每次定义命令都重复编写接口实现代码。以下是RelayCommand的完整实现:
using System;
using System.Windows.Input;
namespace WpfCommandDemo
{
// 自定义命令类,实现ICommand接口
public class RelayCommand : ICommand
{
// 命令执行的逻辑委托
private readonly Action<object> _execute;
// 判断命令是否可执行的委托
private readonly Func<object, bool> _canExecute;
// 构造函数,接收执行逻辑和可选的可执行判断逻辑
public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}
// 判断命令是否可执行
public bool CanExecute(object parameter)
{
// 如果没有传入判断委托,默认返回true
return _canExecute == null || _canExecute(parameter);
}
// 执行命令逻辑
public void Execute(object parameter)
{
_execute(parameter);
}
// 触发CanExecuteChanged事件,通知界面更新命令状态
public void RaiseCanExecuteChanged()
{
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
// 可执行状态变化事件
public event EventHandler CanExecuteChanged;
}
}
ViewModel中定义命令
接下来我们创建一个简单的ViewModel,在ViewModel中定义命令属性,并编写对应的业务逻辑。以下示例实现了一个计数功能,包含增加计数和重置计数两个命令:
using System;
namespace WpfCommandDemo
{
// 实现INotifyPropertyChanged接口,用于属性变化通知界面
public class MainViewModel : System.ComponentModel.INotifyPropertyChanged
{
private int _count;
// 计数属性
public int Count
{
get { return _count; }
set
{
_count = value;
// 属性变化时通知界面更新
OnPropertyChanged(nameof(Count));
// 通知增加命令的可执行状态可能变化
AddCommand.RaiseCanExecuteChanged();
}
}
// 增加计数命令
public RelayCommand AddCommand { get; private set; }
// 重置计数命令
public RelayCommand ResetCommand { get; private set; }
public MainViewModel()
{
Count = 0;
// 初始化增加命令:执行逻辑是计数加1,可执行条件是计数小于10
AddCommand = new RelayCommand(
parameter => Count++,
parameter => Count < 10
);
// 初始化重置命令:执行逻辑是计数归零,无执行条件限制
ResetCommand = new RelayCommand(parameter => Count = 0);
}
// 属性变化事件
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
// 触发属性变化通知
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
}
XAML界面中绑定命令
最后在XAML界面中,将按钮等元素的Command属性绑定到ViewModel中定义的命令属性,即可完成命令绑定。以下是完整的XAML示例代码:
<Window x:Class="WpfCommandDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfCommandDemo"
Title="WPF命令绑定示例" Height="300" Width="400">
<Window.DataContext>
<!-- 设置窗口的数据上下文为MainViewModel实例 -->
<local:MainViewModel />
</Window.DataContext>
<Grid>
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock Text="{Binding Count}" FontSize="24" HorizontalAlignment="Center" Margin="0,0,0,20"/>
<Button Content="增加计数" Command="{Binding AddCommand}" Width="120" Height="30" Margin="0,0,0,10"/>
<Button Content="重置计数" Command="{Binding ResetCommand}" Width="120" Height="30"/>
</StackPanel>
</Grid>
</Window>
命令参数传递
如果需要在执行命令时传递参数,可以使用CommandParameter属性。例如修改增加命令,支持传递自定义的增加步长:
// ViewModel中修改AddCommand初始化逻辑
AddCommand = new RelayCommand(
parameter =>
{
// 如果传入的参数是数字,按参数步长增加,否则默认加1
if (parameter is int step)
{
Count += step;
}
else
{
Count++;
}
},
parameter => Count < 10
);
XAML中绑定命令参数:
<Button Content="增加2" Command="{Binding AddCommand}" CommandParameter="2" Width="120" Height="30" Margin="0,0,0,10"/>
常见注意事项
- 如果命令的可执行状态依赖多个属性,需要在所有相关属性变化时调用RaiseCanExecuteChanged方法,否则界面不会更新命令的可用状态
- 命令的Execute和CanExecute方法的parameter参数可以为null,编写逻辑时需要做好空值判断
- 如果不需要判断命令是否可用,CanExecute委托可以传入null,命令会默认始终可用
WPFICommand命令绑定RelayCommand修改时间:2026-07-24 04:51:30