Use the
MVVM ToolKit[
^]. One of the thinks that they have is a
RelayCommand[
^] that will make life simple for you.
But if you want to roll-your-own, here is one that I use:
public class RelayCommand : RelayCommand<object>
{
public RelayCommand(Action<object> execute)
: base(execute) { }
public RelayCommand(Action<object> execute, Predicate<object>? canExecute)
: base(execute, canExecute) { }
}
public class RelayCommand<TValue> : ICommand
{
#region Fields
private readonly Action<TValue> _execute;
private readonly Predicate<TValue>? _canExecute;
private EventHandler? _internalCanExecuteChanged;
#endregion
#region Constructors
public RelayCommand(Action<TValue> execute)
: this(execute, null) { }
public RelayCommand(Action<TValue> execute, Predicate<TValue>? canExecute)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}
#endregion
#region ICommand Members
public event EventHandler? CanExecuteChanged
{
add
{
_internalCanExecuteChanged += value;
CommandManager.RequerySuggested += value;
}
remove
{
_internalCanExecuteChanged -= value;
CommandManager.RequerySuggested -= value;
}
}
public void RaiseCanExecuteChanged()
{
if (_canExecute != null)
OnCanExecuteChanged();
}
public void Execute(object? parameter)
=> _execute((parameter is null ? default : (TValue)parameter)!);
public bool CanExecute(object? parameter)
=> _canExecute == null || (parameter is null ? _canExecute(default!) : _canExecute((TValue)parameter));
protected virtual void OnCanExecuteChanged()
{
EventHandler? eCanExecuteChanged = _internalCanExecuteChanged;
if (eCanExecuteChanged == null)
return;
eCanExecuteChanged(this, EventArgs.Empty);
}
#endregion
}
To use...
1. declare a property:
public RelayCommand MyCommand { get; set; }
2. Initialise in the constructor:
MyCommand = new RelayCommand(execute: MyMethod, canExecute: _ => true);
3. The Method that executes:
private void MyMethod(object obj)
{
}