Wednesday, October 12, 2016

ICommand and Command

1. Command are loosely typed events.
2. ICommand interface is used to implement command in MVVM
3. ICommand interface exist in System.Window.Input
4. ICommand interface contains two methods Execute, Canexecute and one event handler CanExecuteChanged.

To bind a command of a button you need to bind a property of type  ICommand. An ICommand contains
  1. event EventHandler CanExecuteChanged;    
  2. bool CanExecute(object parameter);    
  3. void Execute(object parameter);    
CanExecuteChanged is invoked when changes occur that can change whether or not the command can be executed.

CanExecute will determine whether the command can be executed or not. If it returns false the button will be disabled on the interface.

Execute runs the command logic.

With a simple implementation of ICommand I can create the following:
  1. public class NormalCommand : ICommand    
  2. {    
  3.     public event EventHandler CanExecuteChanged;    
  4.      
  5.     public bool CanExecute(object parameter)    
  6.     {    
  7.           
  8.     }    
  9.      
  10.     public void Execute(object parameter)    
  11.     {    
  12.          
  13.     }    
  14. }   
However this does not allow me to have a different logic to my CanExecute or Execute. For each command I would need to implement a new class. To solve that problem there is the RelayCommandimplementation that is a command that can be instantiated passing the actions to be executed as in the following:
  1. public class RelayCommand : ICommand    
  2. {    
  3.     private Action<object> execute;    
  4.     private Func<objectbool> canExecute;    
  5.      
  6.     public event EventHandler CanExecuteChanged    
  7.     {    
  8.         add { CommandManager.RequerySuggested += value; }    
  9.         remove { CommandManager.RequerySuggested -= value; }    
  10.     }    
  11.      
  12.     public RelayCommand(Action<object> execute, Func<objectbool> canExecute = null)    
  13.     {    
  14.         this.execute = execute;    
  15.         this.canExecute = canExecute;    
  16.     }    
  17.      
  18.     public bool CanExecute(object parameter)    
  19.     {    
  20.         return this.canExecute == null || this.canExecute(parameter);    
  21.     }    
  22.      
  23.     public void Execute(object parameter)    
  24.     {    
  25.         this.execute(parameter);    
  26.     }    
  27. }  
With this implementation I can specify what I want to execute when I create the command, so I don't need to implement a new class for each different action I want to take. Then it could be called using the following:
  1. var cmd1 = new RelayCommand(o => { /* do something 1 */ }, o => true);    
  2. var cmd2 = new RelayCommand(o => { /* do something 2 */ }, o => true);   
The CommandManager.RequerySuggested handles events when something in the interface suggests that a requery should happen. If your ICommand adds the handlers to it then it will automatically update UI elements when the screen executes some actions. (For example, lose focus on a TextBox.)

No comments:

Followers

Link