ICommand MVVM implementation
This is almost identical to how Karl Shifflet demonstrated a RelayCommand
, where Execute
fires a predetermined Action<T>
. A top-notch solution, if you ask me.
public class RelayCommand : ICommand{ private readonly Predicate<object> _canExecute; private readonly Action<object> _execute; public RelayCommand(Predicate<object> canExecute, Action<object> execute) { _canExecute = canExecute; _execute = execute; } 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); }}
This could then be used as...
public class MyViewModel{ private ICommand _doSomething; public ICommand DoSomethingCommand { get { if (_doSomething == null) { _doSomething = new RelayCommand( p => this.CanDoSomething, p => this.DoSomeImportantMethod()); } return _doSomething; } }}
Read more:
Josh Smith (introducer of RelayCommand
): Patterns - WPF Apps With The MVVM Design Pattern
I have written this article about the ICommand interface.
The idea - creating a universal command that takes two delegates: one is called when ICommand.Execute (object param)
is invoked, the second checks the status of whether you can execute the command (ICommand.CanExecute (object param))
.
Requires the method to switching event CanExecuteChanged
. It is called from the user interface elements for switching the state CanExecute()
command.
public class ModelCommand : ICommand{ #region Constructors public ModelCommand(Action<object> execute) : this(execute, null) { } public ModelCommand(Action<object> execute, Predicate<object> canExecute) { _execute = execute; _canExecute = canExecute; } #endregion #region ICommand Members public event EventHandler CanExecuteChanged; public bool CanExecute(object parameter) { return _canExecute != null ? _canExecute(parameter) : true; } public void Execute(object parameter) { if (_execute != null) _execute(parameter); } public void OnCanExecuteChanged() { CanExecuteChanged(this, EventArgs.Empty); } #endregion private readonly Action<object> _execute = null; private readonly Predicate<object> _canExecute = null;}
I've just created a little example showing how to implement commands in convention over configuration style. However it requires Reflection.Emit() to be available. The supporting code may seem a little weird but once written it can be used many times.
Teaser:
public class SampleViewModel: BaseViewModelStub{ public string Name { get; set; } [UiCommand] public void HelloWorld() { MessageBox.Show("Hello World!"); } [UiCommand] public void Print() { MessageBox.Show(String.Concat("Hello, ", Name, "!"), "SampleViewModel"); } public bool CanPrint() { return !String.IsNullOrEmpty(Name); }}
}
UPDATE: now there seem to exist some libraries like http://www.codeproject.com/Articles/101881/Executing-Command-Logic-in-a-View-Model that solve the problem of ICommand boilerplate code.