WPF MVVM框架 - Prism DelegateCommand 命令绑定

287

在 WPF 的 Prism 框架中,DelegateCommand 是实现 ICommand 接口的核心组件,专门用于 MVVM 模式中的命令绑定。

它的主要功能是将 UI 操作(如按钮点击)与 ViewModel 中的逻辑解耦,同时支持条件执行(例如控制按钮是否可点击)。

核心功能

委托绑定

通过委托(Delegate)定义命令的实际操作(Execute)和是否允许执行的判断逻辑(CanExecute)

public DelegateCommand ClickCommand { get; private set; }

// 构造函数中初始化
public MyViewModel()
{
    ClickCommand = new DelegateCommand(OnClick, CanClick);
}

private void OnClick() 
    => MessageBox.Show("Command executed!");

private bool CanClick() 
    => IsButtonEnabled; // 返回 true/false 控制按钮状态

参数传递

支持泛型 DelegateCommand<T> 传递参数(例如从 UI 元素获取输入)

public DelegateCommand<string> SubmitCommand { get; private set; }

public MyViewModel()
{
    SubmitCommand = new DelegateCommand<string>(OnSubmit, CanSubmit);
}

private void OnSubmit(string parameter) 
    => MessageBox.Show($"Input: {parameter}");

private bool CanSubmit(string parameter) 
    => !string.IsNullOrEmpty(parameter);

动态状态更新

通过 RaiseCanExecuteChanged() 手动触发 CanExecute 重新验证,更新 UI 控件的启用状态

private bool _isEnabled;
public bool IsEnabled
{
    get => _isEnabled;
    set
    {
        _isEnabled = value;
        ClickCommand.RaiseCanExecuteChanged(); // 通知 UI 更新按钮状态
    }
}

使用场景

按钮点击

将按钮的 Command 属性绑定到 ViewModel 的 DelegateCommand:

<Button Content="Click Me" Command="{Binding ClickCommand}" />

条件性操作

根据业务逻辑动态控制命令是否可用(例如表单验证通过后才允许提交):

private bool CanSubmit(string input) 
    => input?.Length > 5;

优势

解耦 UI 与逻辑:View 仅负责触发命令,具体逻辑由 ViewModel 处理。

可测试性:命令逻辑可通过单元测试直接验证,无需依赖 UI 自动化。

灵活性:支持同步/异步操作(结合 async/await 和 DelegateCommand 封装)。

注意事项

内存泄漏:确保命令在不需要时解除订阅(通常 Prism 已处理内部逻辑)。

UI 线程:若在非 UI 线程更新状态,需通过 Dispatcher 调用 RaiseCanExecuteChanged。

完整示例

ViewModel

public class MainViewModel : BindableBase
{
    private string _inputText;
    public string InputText
    {
        get => _inputText;
        set => SetProperty(ref _inputText, value, () => SubmitCommand.RaiseCanExecuteChanged());
    }

    public DelegateCommand SubmitCommand { get; }

    public MainViewModel()
    {
        SubmitCommand = new DelegateCommand(Submit, CanSubmit);
    }

    private void Submit()
        => MessageBox.Show($"Submitted: {InputText}");

    private bool CanSubmit()
        => !string.IsNullOrEmpty(InputText);
}

View

<StackPanel>
    <TextBox Text="{Binding InputText, UpdateSourceTrigger=PropertyChanged}" />
    <Button Content="Submit" Command="{Binding SubmitCommand}" />
</StackPanel>