在 Action<object> 列表中使用多个 Action

Using multiple Actions in Action<object> list

我正在进一步学习如何使用 ICommand 界面以及如何通过我创建的 RelayCommand class 执行命令。

首先,我对我想要实现的目标做了一些研究,但我找不到任何可以帮助我的东西,或者我真的不知道如何搜索我想要做的事情。另外,我对 C# 理论的了解不是很好,所以这也不利于我。

基本上我试图将多个动作发送到我的 RelayCommand 构造函数,然后遍历 List<Action<object>> 集合中的所有动作并一个一个地执行它们。这是我的代码:

RelayCommand class 构造函数

public RelayCommand(Predicate<object> canExecute, List<Action<object>> actions)
{
    _canExecute = canExecute;

    foreach (var action in actions)
        _execute = action;
}

然后我的命令 属性 在我的 ViewModel

private ICommand _updateExternals;
public ICommand UpdateExternals
{
    get
    {
        if (_updateExternals == null)
        {
            _updateExternals = new RelayCommand(
                x => CanExecute,
                Updater.UpdateExternals(this));//Here is where I am stuck
        }
        return _updateExternals;
    }
}

我从其他例子中知道,如果我只需要传递一个 Action 而不是一个 Action 列表,那么代码将如下所示:x => Updater.UpdateExternals(this)); 并且它会工作,但只要我有一个动作列表作为参数,我就会卡住。

所以,如果您还没有猜到的话,我的问题是:如何将多个 Action 发送到我的 RelayCommand class?

任何正确方向的帮助将不胜感激,谢谢!

编辑: 这是我的完整 RelayCommand class 可以让我更清楚地了解我在做什么。

public class RelayCommand : ICommand
{
    private Predicate<object> _canExecute;
    private Action<object> _execute;

    public RelayCommand(Predicate<object> canExecute, List<Action<object>> actions)
    {
        _canExecute = canExecute;
        foreach (var action in actions)
            _execute = action;
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

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

    public void Execute(object parameter)
    {
        _execute(parameter);
    }
}

您的 class 需要包含您要执行的操作的列表,因此请将其作为一个字段添加到您的 class 中,然后在构造函数中进行设置。 然后在您的 Execute 方法(接口实现)中,您只需遍历操作并一个接一个地调用它们。

public class RelayCommand : ICommand
{
    private Predicate<object> _canExecute;
    private List<Action<object>> _executes;

    public RelayCommand(Predicate<object> canExecute, List<Action<object>> actions)
    {
        _canExecute = canExecute;
        _executes = actions;
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

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

    public void Execute(object parameter)
    {
        foreach(e in _executes )
        {            
           e(parameter);
        }
    }
}

您的原始代码所做的是为构造函数参数中的每个操作一遍又一遍地分配单个操作引用,因此您的 class 只会在 [=11] 时执行列表中的最后一个操作=] 被调用。

记住 ActionAction<T> 或多或少只是对某个方法的引用,命名或匿名 (lambda)。

要解决您的问题,请在构造函数中使用 params

public class RelayCommand : ICommand {
    private Predicate<object> _canExecute;
    private Action<object>[] _execute;

    public RelayCommand(Predicate<object> canExecute, params Action<object>[] actions) {
        _canExecute = canExecute;
        _execute = actions;
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

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

    public void Execute(object parameter) {
        foreach (var action in _execute)
            action(parameter);
    }
}

然后你可以像往常一样创建这样的命令:

_updateExternals = new RelayCommand(
    x => CanExecute,
    x => Updater.UpdateExternals(this));//Here is where I am stuck

当您需要传递多个动作时:

_updateExternals = new RelayCommand(
    x => CanExecute,
    x => Updater.UpdateExternals(this),
    x => Updater.DoSomethingElse(this));