5 Simple Steps to Commanding in Silverlight

Implementing ICommand in your Silverlight 4 project only requires a few steps. I have had a dozens of questions about this lately so I decided to share a very simple technique to implement commanding in Silverlight 4.

Step 1 – Implement ICommand

The first step is to implement the ICommand interface with a class that will manage the commanding aspects. There are other options to do this, but here is a simplified yet powerful implementation of ICommand.

The DelegatedCommand class implements ICommand’s CanExecute method, the Execute method, and the CaneExecuteChanged event. This code can be copied and used “as is”.

   1: public class DelegateCommand : ICommand
   2: {
   3:     Func<object, bool> canExecute;
   4:     Action<object> executeAction;
   5:     bool canExecuteCache;
   6:  
   7:     public DelegateCommand(Action<object> executeAction, Func<object, bool> canExecute)
   8:     {
   9:         this.executeAction = executeAction;
  10:         this.canExecute = canExecute;
  11:     }
  12:  
  13:     #region ICommand Members
  14:  
  15:     public bool CanExecute(object parameter)
  16:     {
  17:         bool temp = canExecute(parameter);
  18:  
  19:         if (canExecuteCache != temp)
  20:         {
  21:             canExecuteCache = temp;
  22:             if (CanExecuteChanged != null)
  23:             {
  24:                 CanExecuteChanged(this, new EventArgs());
  25:             }
  26:         }
  27:  
  28:         return canExecuteCache;
  29:     }
  30:  
  31:     public event EventHandler CanExecuteChanged;
  32:  
  33:     public void Execute(object parameter)
  34:     {
  35:         executeAction(parameter);
  36:     }
  37:  
  38:     #endregion
  39: }

Step 2 – Define the Command

Add a public property to your ViewModel to represent the ICommand. This property will be bound to your View through a button, generally.

public ICommand LoadProductsCommand { get; set; }

Step 3 – Create the Command

In the constructor of your ViewModel, set the command property you created in step 1.

LoadProductsCommand = new DelegateCommand(LoadProducts, CanLoadProducts);

Step 4 – Create the VM

You must then make sure your ViewModel is accessible in your View. This is can be done in many ways. But for simplicity I am showing the ViewModel created as a static resource in the View’s XAML.

<UserControl.Resources>
    <local:ProductViewModel x:Key="vm"/>
</UserControl.Resources>

Step 5 – Bind the Command

Add a button control and bind the Command property to the command you created in the ViewModel. Then if you need to pass a parameter into the command you can bind the CommandParameter property to an element in the View. I find that I generally do not need to pass a parameter in, but I added this here as an example.

<Button Content="Load" Width="120"
    Command="{Binding LoadProductsCommand}"
    CommandParameter="{Binding ElementName=FilterTextBox, Path=Text}" />

That’s it! 5 simple steps and now you have commanding in your application.

Want More …

I included the key code files in the post, below. No need to dive into them unless you want to grab the code as a starting point.

The complete ProductViewModel code can be seen here:

   1: public class ProductViewModel : ViewModelBase
   2: {
   3:     public ProductViewModel()
   4:     {
   5:         this.Products = new ObservableCollection<Product>();
   6:  
   7:         // Warning: DEMO CODE AHEAD
   8:         // Your ViewModel should not define your data for your Model :-)
   9:         // Instead, it could make a call to a service to get the data for the Model.
  10:         this.AllProducts = new ObservableCollection<Product>();
  11:         this.AllProducts.Add(new Product { ProductId = 1, ProductName = "Apple" });
  12:         this.AllProducts.Add(new Product { ProductId = 2, ProductName = "Orange" });
  13:         this.AllProducts.Add(new Product { ProductId = 3, ProductName = "Banana" });
  14:         this.AllProducts.Add(new Product { ProductId = 4, ProductName = "Pear" });
  15:         this.AllProducts.Add(new Product { ProductId = 5, ProductName = "Grape" });
  16:         this.AllProducts.Add(new Product { ProductId = 6, ProductName = "Grapefruit" });
  17:         this.AllProducts.Add(new Product { ProductId = 7, ProductName = "Strawberry" });
  18:         this.AllProducts.Add(new Product { ProductId = 8, ProductName = "Melon" });
  19:         this.AllProducts.Add(new Product { ProductId = 9, ProductName = "Guava" });
  20:         this.AllProducts.Add(new Product { ProductId = 10, ProductName = "Kiwi" });
  21:         this.AllProducts.Add(new Product { ProductId = 11, ProductName = "Pineapple" });
  22:         this.AllProducts.Add(new Product { ProductId = 12, ProductName = "Mango" });
  23:  
  24:         LoadProductsCommand = new DelegateCommand(LoadProducts, CanLoadProducts);
  25:     }
  26:  
  27:     private void LoadProducts(object param)
  28:     {
  29:         string filter = param as string ?? string.Empty;
  30:         this.Products.Clear();
  31:         var query = from p in this.AllProducts
  32:                     where p.ProductName.ToLower().StartsWith(filter.ToLower())
  33:                     select p;
  34:         foreach (var item in query)
  35:         {
  36:             this.Products.Add(item);
  37:         }
  38:     }
  39:  
  40:     private bool CanLoadProducts(object param)
  41:     {
  42:         return true;
  43:     }
  44:  
  45:     public ICommand LoadProductsCommand { get; set; }
  46:  
  47:     public ObservableCollection<Product> AllProducts { get; set; }
  48:  
  49:     private ObservableCollection<Product> products;
  50:     public ObservableCollection<Product> Products
  51:     {
  52:         get
  53:         {
  54:             return products;
  55:         }
  56:         set
  57:         {
  58:             products = value;
  59:             this.FirePropertyChanged("Product");
  60:         }
  61:     }
  62: }
  63:  

Here is the ViewModelBase class. It simply contains the FirePropertyChanged event that all ViewModel classes will use in my project.

   1: public abstract class ViewModelBase : INotifyPropertyChanged
   2: {
   3:     public ViewModelBase()
   4:     {
   5:     }
   6:  
   7:     public event PropertyChangedEventHandler PropertyChanged;
   8:  
   9:     protected void FirePropertyChanged(string propertyname)
  10:     {
  11:         var handler = PropertyChanged;
  12:         if (handler != null)
  13:             handler(this, new PropertyChangedEventArgs(propertyname));
  14:     }
  15:  
  16: }
Tweet Post Share Update RSS

Hi, I'm John Papa. I author this blog, create courses for Pluralsight and am a Google Developer Expert and Microsoft Regional Director. I travel speaking at events and train technology thought leaders

Tags:
Silverlight