Search code examples
c#actionicommand

Using multiple Actions in Action<object> list


I'm learning a bit more about using the ICommand interface and how to execute commands through the RelayCommand class I created.

Firstly, I did some research on what I am trying to achieve, but I can't find anything to help me or I do not really know how to search for what I am trying to do. Also, my knowledge of C# theory isn't really good so that's also not in my favour.

Basically I'm trying to send multiple actions through to my RelayCommand constructor and then iterate through all of the actions in the List<Action<object>> collection and execute them one by one. Here is my code:

RelayCommand class constructor

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

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

And then my command property inside my 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;
    }
}

I know, from other examples, that if I only need to pass through a single Action instead of a list of Actions that the code would look like the following: x => Updater.UpdateExternals(this)); and it would work, but as soon as I have a list of Actions as a parameter I get stuck.

So, if you haven't already guessed, my question is: How can I send through multiple Actions to my RelayCommand class?

Any help in the right direction would be appreciated, thanks!

EDIT: Here is my full RelayCommand class to give more of an idea of what I am doing.

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);
    }
}

Solution

  • To solve your problem, use params in constructor:

    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);
        }
    }
    

    Then you can create such command as usual:

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

    When you need to pass multiple actions:

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