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);
}
}
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));
Your class needs to have a list of the actions you want to execute, so add that as a field in your class and then set it in the constructor. Then in your Execute method (interface implementation) you just iterate over the actions and call them one after another.
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);
}
}
}
What you original code was doing was assigning the single action reference over and over with each of the actions from the constructor parameter so your class would only have executed the last action in the list when Execute
is called.
Remember an Action
and Action<T>
is more or less just a reference to some method, named or anonymous (lambda).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With