C# ICommand 可以执行

C# ICommand Can Execute

我试图了解 ICommand 接口。我构建了一个带有按钮的应用程序,该按钮使用一个名为 RelayCommand 的 class,它继承自 ICommand。 class 看起来像这样:

    class RelayCommand : ICommand
{
    private Action<object> _action;
    public RelayCommand(Action<object> action)
    {
        _action = action;
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        if(parameter != null)
        {
            _action(parameter);
        }
        else
        {
            _action("Hello World");
        }
    }

    //We need to include CanExecuteChange when using the Interface ICommand 
    //In this case it doesn't actually do anything.
    public event EventHandler CanExecuteChanged;

}

每次我跟踪函数时,我都会点击 CanExecute 方法,但现在我在代码中的某个地方调用了这个方法。我像这样创建一个 RelayCommand 实例:

Btn_AcceptedAnswer = new RelayCommand(new Action<object>(AcceptedAnswer_OnClick));

所以我的问题是,当RelayCommand启动的时候,它是怎么知道运行 CanExecute()和Execute()的,什么时候运行这些的?我知道如何实现一个事件,我只是想了解它是如何工作的。

UI (WPF) 正在调用 CanExecute 以了解是否必须启用与命令关联的按钮。

Execute 在按下按钮时被调用。

您可以在 CanExecute 的条件发生变化时引发(调用)CanExecuteChanged 事件,以通知 UI 重新查询它。例如,该命令可以是与绑定到网格视图、组合框等的列表集合相关的 "Clear" 命令。如果列表从空变为非空或反之,则提高 CanExecuteChanged。当然,该按钮只有在列表不为空时才会启用。

public bool CanExecute(object parameter)
{
    return myList.Count > 0;
}

private void OnCanExecuteChanged()
{
    CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}

public void Execute(object parameter)
{
    if(myList.Count > 0) {
        myList.Clear();
        OnCanExecuteChanged();
    }
}

向列表中添加元素时,您也应该触发该事件。然而,这更棘手,因为这很可能发生在另一个命令中。您将需要一种在两者之间进行通信的方法。一个好的方法是使用 ObservableCollection<T> or a BindingList<T>. Both raise events when the list changes (see: Difference between ObservableCollection and BindingList)。然后命令可以订阅绑定列表事件。 BindingList<T> 的另一个效果是它绑定到的 UI 元素会在列表更改时自动更新。