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

# Silverlight 4 - MVVM with Commanding and WCF RIA Services

Monday, November 30, 2009 1:38 PM by Fredrik Normén

Note: The code example in this post uses Silverlight 4 PDC Beta and WCR RIA Services PDC Beta, so some

# Silverlight 4 - MVVM with Commanding and WCF RIA Services

Monday, November 30, 2009 1:43 PM by Cornerstones utvecklarblogg

Note: The code example in this post uses Silverlight 4 PDC Beta and WCR RIA Services PDC Beta, so some

# Silverlight 4 - MVVM with Commanding and WCF RIA Services

Monday, November 30, 2009 2:34 PM by ASPInsiders

Note: The code example in this post uses Silverlight 4 PDC Beta and WCR RIA Services PDC Beta, so some

# Silverlight: getting started with commands

Thursday, April 01, 2010 2:37 PM by LA.NET [EN]

Silverlight 4.0 added the notion of command. In practice, a command is any object which implements the

# Silverlight: getting started with commands

Thursday, April 01, 2010 2:38 PM by LA.NET [PT]

Silverlight 4.0 added the notion of command. In practice, a command is any object which implements the

# Silverlight: getting started with commands

Thursday, April 01, 2010 3:13 PM by ASPInsiders

Silverlight 4.0 added the notion of command. In practice, a command is any object which implements the

# re: Silverlight 4 Commanding enables ViewModels

Thursday, July 29, 2010 11:02 AM by Debashish Gupta

Commands not being Invoked in my View Model Class.

Hi , I am developing an MVVM Application. I am following the johnpapa.net/.../5-simple-steps-to-commanding-in-silverlight

I have a listBox showing all the Employee Names and beside it is the details of every employee.

On click of a diffrent employee from the listBox we get the details of the Next Employee.

I have also kept 4 Commands . But i am not sure why my commands in the VM is not getting called on click from View.

--VIEW CLASS-------------------------------------------------------------------

<ListBox Name="lstMiners" Grid.Row="0" Grid.Column="0" Margin="5"

                ItemsSource="{Binding Path=MinerList, Mode=TwoWay}"

                SelectedItem="{Binding Path=SelectedMiner, Mode=TwoWay}" >

               <ListBox.ItemTemplate>

                   <DataTemplate>

                       <StackPanel Orientation="Horizontal">

                           <TextBlock Text="{Binding Miner_First_Name}" FontWeight="Bold" />                            

                       </StackPanel>

                   </DataTemplate>

               </ListBox.ItemTemplate>

           </ListBox>

<Grid x:Name="MinerDetails" Grid.Column="1" Grid.Row="0"

                 DataContext="{Binding Path=SelectedMiner, Mode=TwoWay}"

                     Margin="5" Background="LightGray">

               <Grid.ColumnDefinitions>

                   <ColumnDefinition Width="100" />

                   <ColumnDefinition Width="100" />

               </Grid.ColumnDefinitions>

               <Grid.RowDefinitions>

                   <RowDefinition Height="20" />

                   <RowDefinition Height="20" />

                   <RowDefinition Height="20" />

                   ......

               </Grid.RowDefinitions>

               <TextBlock Grid.Row="1" Grid.Column="0" Text="Miner_id:"  />

               <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Path=Miner_id, Mode=TwoWay}" IsEnabled="False" />

               <TextBlock Grid.Row="2" Grid.Column="0" Text="First Name:" />

               <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Path=Miner_First_Name,Mode=TwoWay}" />

               <TextBlock Grid.Row="3" Grid.Column="0" Text="Last Name:" />

               <TextBox Grid.Row="3" Grid.Column="1" Text="{Binding Path=Miner_Last_Name,Mode=TwoWay}" />

               .....

           </Grid>

<StackPanel Orientation="Horizontal" Grid.Row="1" HorizontalAlignment="Left"        DataContext="Binding">

           ... <Button Command="{Binding SaveCommand}"     Content="Save" Height="25" Width="100" Background="Aqua"></Button>

       </StackPanel>

--VIEW MODEL CLASS----------------------------------------------------------------------------------------------------------

       public ICommand SaveCommand { get; set; }        

In Constructor...

public MinerMasterVM()

       {

           SaveCommand = new DelegateCommand(SaveMiner, CanSaveMiner);

           MinerServiceClient msClient = new MinerServiceClient();

           msClient.GetMinersCompleted += new EventHandler<GetMinersCompletedEventArgs>(msClient_GetMinersCompleted);

           msClient.GetMinersAsync();

       }

public void SaveMiner(object parameter)

       {

           ....

       }

       void msClient_UpdateMinerCompleted(object sender, UpdateMinerCompletedEventArgs e)

       {

           throw new NotImplementedException();

       }

       private bool CanSaveMiner(object parameter)

       {

           return true;

       }

-----------------------------------------------------------------------------------------------------

I am calling the View XMAL file from the MainPage.XMAL.

<

views:MinerView x:Name="MinerDataView"></views:MinerView>

MinerMasterVM mVM = new MinerMasterVM();

MinerDataView.DataContext = mVM;

All my VM objects are accessible . But not the Commands .

Not sure Why . Can some body through some light on it.

Regards

Debashish

Leave a Comment

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