Silverlight 4 Commanding enables ViewModels

One feature out of many really great feature shipped with Silverlight 4 Beta, is Commanding. With Commanding we can use the MVVM (Model View View Model) Pattern. Commanding is something that WPF has and preview Silverlight doesn’t. Commanding can only be used on ButtonBase controls and Hyperlink control at the moment, and will only be executed by the Click event. In this post I’m going to show how you can use the new Commanding feature and create use the MVVM pattern in Silverlight 4. Here is my simple UI:

ui


I have a TextBox and a Button. The ViewModel will represent this view but in code. The main reason to use a ViewModel is because of separation of concerns. The complex UI logic is moved from the View into a class (the ViewModle). The ViewModel for the View above will look like this:

public class CustomerViewModel : INotifyPropertyChanged
{
     public event PropertyChangedEventHandler PropertyChanged;

     private string _firstName;

     public string FirstName
     {
         get { return _firstName; }
         set
         {
             //Validation code
            _firstName = value;

            //NotifyPropertyChange
         }
     }

     public ICommand Save
     {
        get { return new SaveCommand(this); }
     }
 }


The FirsrtName property represents the TextBox in the View, the Save property is the Command that should be executed when the Save button is clicked. As you can see the Save member is a property which will return a ICommand, in this case the SaveCommand. Here is the SaveCommand class:

public class SaveCommand : ICommand
{
    private CustomerViewModel _view;

    public SaveCommand(CustomerViewModel view)
    {
        _view = view;
    }

    public bool CanExecute(object parameter)
    {
            return true;
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
         //Do something like saving the Customer
     }
}


The SaveCommand implements the ICommand interface which has three members, the CanExecute property, CanExecuteChanged event and the Execute method. The CanExecute return true or false if the command can be executed. The method takes one parameter, this parameter comes from the CommandParamter attribute added to the Button or Hyperlink. The Execute method, is the method that will be executed if the Command can be executed, it’s where you can add your code to perform something when the user clicks the Save button, for example using WCF RIA Services to save the Customer. When the Command and the ViewModel is in place, we can just bind the ViewModel to a DataContext and then use normal Binding to bind to our ViewModel, like this:

<UserControl x:Class="SilverlightApplication3.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vm="clr-namespace:SilverlightApplication3">
    <UserControl.Resources>
        <vm:CustomerViewModel x:Name="myViewModel"/>
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" DataContext="{StaticResource myViewModel}">
        <TextBlock  Text="First Name:" ... />
        <TextBox Text="{Binding FirstName, Mode=TwoWay}" .../>
        <Button CommandParameter="test" Command="{Binding Save}" Content="Save"  ..." />
    </Grid>
</UserControl>


As you can see the CustomerViewModel is added to the UserControl’s Resources and then added to the LayoutRoot’s DataContext. The TextBox is bind to the FirstName property of the ViewModel and the Command attribute of the Button is bind to the Save property. I just added the CommandParameter to the code so you can see how it can be used to pass a parameter into the CanExecute and Execute method.

I hope the Silverlight team will also add a way to specify an ViewModel method to any kind of events and where we don’t need to implement the ICommand interface. The Commanding often results in many Command classes.

Published Thursday, November 19, 2009 12:41 AM by Fredrik N

Comments

No Comments

Leave a Comment

(required) 
(required) 
(optional)
(required)