WPF中的命令的实现与参数传递
在MVVM中,有下面几种实现命令的方式
一、实现命令的常见方式:DelegateCommand(或RelayCommand)
public class DelegateCommand : ICommand
{
private readonly Action<object> _execute;
private readonly Func<object, bool> _canExecute;
public event EventHandler CanExecuteChanged;
public DelegateCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter) => _canExecute?.Invoke(parameter) ?? true;
public void Execute(object parameter) => _execute(parameter);
public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
// 在ViewModel中的使用
public class MainViewModel
{
public ICommand SaveCommand { get; }
public ICommand DeleteCommand { get; }
public MainViewModel()
{
SaveCommand = new DelegateCommand(OnSave, CanSave);
DeleteCommand = new DelegateCommand<Customer>(OnDelete, CanDelete);
}
private void OnSave(object parameter) { ... }
private bool CanSave(object parameter) { ... }
private void OnDelete(Customer customer) { ... }
private bool CanDelete(Customer customer) { ... }
}
二、使用Microsoft的CommunityToolkit.Mvvm中的RelayCommand
using CommunityToolkit.Mvvm.Input;
public partial class MainViewModel
{
[RelayCommand]
private void Save()
{
// 无参数命令
}
[RelayCommand]
private void Delete(Customer customer)
{
// 带参数命令
}
// 异步命令
[RelayCommand]
private async Task LoadDataAsync()
{
await Task.Delay(1000);
}
}
三、使用Prism框架的DelegateCommand
using Prism.Commands;
public class MainViewModel
{
public DelegateCommand SaveCommand { get; }
public DelegateCommand<Customer> DeleteCommand { get; }
public MainViewModel()
{
SaveCommand = new DelegateCommand(Save, CanSave);
DeleteCommand = new DelegateCommand<Customer>(Delete, CanDelete);
}
}
优缺点比较:
自定义DelegateCommand:灵活,但需要自己实现;适用于不想引入外部框架的项目。
CommunityToolkit.Mvvm:现代,代码简洁,支持异步命令和属性通知,推荐在新项目中使用。
Prism的DelegateCommand:功能强大,适用于使用Prism框架的大型项目。
带参数的命令示例(XAML中绑定):
xml
<!-- 按钮直接绑定到命令,CommandParameter可以是固定值或绑定 -->
<Button Content="Delete"
Command="{Binding DeleteCommand}"
CommandParameter="{Binding SelectedCustomer}" />
<!-- 列表项中每个项都有一个按钮,CommandParameter绑定到当前项 -->
<ListBox ItemsSource="{Binding Customers}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" />
<Button Content="Delete"
Command="{Binding DataContext.DeleteCommand, RelativeSource={RelativeSource AncestorType=ListBox}}"
CommandParameter="{Binding}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

浙公网安备 33010602011771号