There are some good posts around on how to use Silverlight’s new Command functionality.
Silverlight 4 – How to Command Control – a good overview and how to use a DelegateCommand (also used by Prism) to simplify things.
MVVM Toolkit Light – RelayCommand – similar to the DelegateCommand approach
Nikhil’s Silverlight.FX- this is a great project by Nikhil that includes some great work to simplify implementing Commands in XAML and taking the concept beyond Buttons and Hyperlinks.
However, in most articles I’ve read the main focus has been to avoid the View wiring up events to call directly into ViewModel methods (frowned upon by many!). While this is a side-effect of the implementation it’s not the real motivation behind the Command pattern. The pattern is generally used to encapsulate the concept of a command, allowing it to be reused across your application in potentially different contexts (the classic example being a Save command that can be called from the File – Save menu, from the Save Button and from pressing Ctrl-S).
But there is a cost to implementing this pattern – it requires more code and should, arguably, only be used when there are multiple clients to a command.
To illustrate the potential cost, without using a Command you may have done this; created a button in your View with a Click event,
<Button x:Name="refreshDirectButton" Content="Refresh" Click="refreshDirectButton_Click"></Button>
And then in the Click event handler call the method on the View’s ViewModel.
private void refreshDirectButton_Click(object sender, RoutedEventArgs e)
{
_viewModel.Refresh();
}
Without going into the details of the Command support in Silverlight (check out the links above) you can now create a class that encapsulates your command and implements the new ICommand interface,
public class MyRefreshCommand: ICommand
{
public bool CanExecute(object parameter)
{
// Also allow this command to be called
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
// Do the work that used to be in your ViewModel's Refresh method
// ...
}
}
Your ViewModel’s Refresh method would now be rewritten to return the Command,
public ICommand Refresh
{
get
{
if (_refreshCommand != null)
{
_refreshCommand = new RefreshCommand();
}
return _refreshCommand;
}
}
And you can now bind you View’s button to this command.
<Button x:Name="refreshButton" Command="{Binding Refresh}" Content="Refresh" ></Button>
Phew! That’s going from 3 lines of code to 11 – almost 400% more code!
Now the DelegateCommand/RelayCommand approaches will use slightly less code but it does raise the question of whether it’s worth the effort.
I personally don’t think there’s much difference between my View’s event handler calling into the ViewModel directly versus Silverlight’s Command DataBinding implementation doing it for me. The end result is identical and equally testable and you could argue the direct approach is more readable.
So does anyone else have a reason why using Commands is a better approach when the command itself doesn’t need to be reused? Maybe I’m missing something.