Thursday, June 30, 2011

Silverlight 4 - Programmatically invoking command's CanExecute status

While developing Silverlight 4 applications with Model-View-ViewModel (MVVM), one of the feature that comforts developers is the command object that implements from ICommand. The ICommand interface exposes two methods Execute and CanExecute and an event CanExecuteChanged. As the name implies, the Execute method is the one to be executed when the command is invoked and CanExecute is the method that specifies the execution status - means, it influences whether the command can be executed or not. For getting core details of ICommand, please refer msdn.

Points to be considered while implementing ICommand
Upon implementing the ICommand, simply what we'll be doing is,
  • Get two delegates that matches the Execute and CanExecute methods' signatures(Action<object> and Func<object, bool> resp) as parameters in the constructor and store them in a locally in the class level scope.
  • Then invoke those delegates in the respective methods. That is Action delegate (Action<object>) in the Execute method and the function delegate (Func<object, bool>) in the CanExecute method.
  • In addition to invoking the action delegate (Action<object>), the Execute method need to call the CanExecute method.
  • In addition to invoking the function delegate (Func<object, bool>), the CanExecute method need to raise the CanExecuteChanged event.
There exists several examples in web on implementing ICommand interface and using it. One such is provided by John Papa here, which details more about commanding.

In Silverlight 4, ButtonBase and Hyperlink supports commanding.

The CanExecute method plays its role visually by enabling or disabling the control it(the command object) is bound to. That is the reason why the CanExecute method is called from the Execute method as it'll validate the execution status at the time of execution.

Now comes the core of this post: From the above explanation it is clear that the CanExecute method is called on the command action of the bound control (example: on click of the control). But in some scenarios, we might need to make a strategy somehow that the CanExecute method need to be invoked in order to reevaluate the execution status. Such scenario arises when changes from some other manipulation affects the logic we use to arrive the return value of CanExecute method. Say as a result of some manipulation your ViewModel changes a property which is used in the CanExecute method. So now you need to programmatically achieve reevaluation of the execution status.

Triggering CanExecuteChanged event will do this for you. Hence its good to have a public method in the class that implements the ICommand to raise the CanExecuteChanged event.

Snippet 1

public void RaiseCanExecuteChanged()
{
    if (CanExecuteChanged != null)
    {
        CanExecuteChanged(this, new EventArgs());
    }
}

Hence RaiseCanExecuteChanged is also one of the important point to be considered when implementing the ICommand, as such scenarios are common in applications with MVVM that uses command.

Additional Info
Prism provides this ICommand implementation through DelegateCommand class, which also exposes the RaiseCanExecuteChanged method.

References
http://msdn.microsoft.com/en-us/library/system.windows.input.icommand(v=vs.95).aspx
http://johnpapa.net/5-simple-steps-to-commanding-in-silverlight

No comments:

Post a Comment

Creative Commons License
This work by Tito is licensed under a Creative Commons Attribution 3.0 Unported License.