Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RelayCommand in C#

I am learning MVVM for C# Silverlight development from

http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

and I am confused about the RelayCommand class mentioned in the context. The code is:

public class RelayCommand : ICommand
{
#region Fields

readonly Action<object> _execute;
readonly Predicate<object> _canExecute;        

#endregion // Fields

#region Constructors

public RelayCommand(Action<object> execute)
: this(execute, null)
{
}

public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
    if (execute == null)
        throw new ArgumentNullException("execute");

    _execute = execute;
    _canExecute = canExecute;           
}
#endregion // Constructors

#region ICommand Members

[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
    return _canExecute == null ? true : _canExecute(parameter);
}

public event EventHandler CanExecuteChanged
{
    add { CommandManager.RequerySuggested += value; }
    remove { CommandManager.RequerySuggested -= value; }
}

public void Execute(object parameter)
{
    _execute(parameter);
}

#endregion // ICommand Members
}

For which I dont really understand how _execute and _canExecute works in this case. (I am new to C# and even not sure what's Action and Predicate. I know they are delegates but whats the difference between them and how they works?)
And also, in the program, I didnt get the line

    add { CommandManager.RequerySuggested += value; }
    remove { CommandManager.RequerySuggested -= value; }

Can someone give me a explaination about this, thank you!

like image 505
Allan Jiang Avatar asked Jul 01 '12 23:07

Allan Jiang


2 Answers

A RelayCommand requires two pieces of information:

  1. What code should run when the command is executed (the _execute action)
  2. What code should run to determine if this command can be executed (the _canExecute predicate)

An Action is a delegate that represents a method that returns void. In this case the _execute action takes one parameter (an object) and returns void.

A Predicate is a delegate that takes a value and returns a boolean result. In this case the _canExecute predicate takes an object value and returns a bool.

Both the _execute and _canExecute values are supplied to the RelayCommand when it is constructed because these are the parts of the command that are unique to each individual command.

Regarding the CanExecuteChanged event:

public event EventHandler CanExecuteChanged
{
    add { CommandManager.RequerySuggested += value; }
    remove { CommandManager.RequerySuggested -= value; }
}

When a subscriber subscribes to the event, add is called and when they unsubscribe, remove is called. The above CanExecuteChanged event is just a pass-through event (i.e. if a subscriber subscribes to the CanExecuteChanged event, they automatically subscribe to the CommandManager.RequerySuggested event). According to MSDN, the CommandManager.RequerySuggested event...

occurs when the CommandManager detects conditions that might change the ability of a command to execute.

I believe that a subscriber would most likely call the CanExecute method on the RelayCommand when this event is fired to determine if the command can still be executed.

like image 128
Kevin Aenmey Avatar answered Oct 13 '22 01:10

Kevin Aenmey


The add/remove are like a property get/set but for events instead. The add code would be called when

RelayCommandInstance.CanExecuteChanged += MyChangedEventHandler 

is executed. The remove code is called when -= is executed. You don't see this syntax very much, since you rarely need to override the default behavior of adding/removing the delegate from the events call list.

In this case, the RelayCommand is just mapping its CanExecuteChanged event to the CommandManager.RequerySuggested event.

like image 43
Japple Avatar answered Oct 13 '22 00:10

Japple