Coming In Mango–ICommand

Mango From Scratch

As noted in earlier posts, Mango represents a move from Silverlight 3+ to Silverlight 4, and ICommand with that comes ICommand on ButtonBase and Hyperlink (and classes that derive from these two). 

This is a significant breakthrough, especially if you are programming with MVVM.  

ICommand allows you to bind an action as a property, thus keeping a clean separation from the controlling class (typically the view model) to the presentation class (typically the view). 

To see this at work, we’ll create a program that retrieves data from a (pseudo-) web service, and displays that data when a button is pushed. 

To do this, I created a new program in Mango. The Xaml consists of a button (Load) and a list box (initially empty).  I opted to put a white border on the list box so that it acts as a placeholder.

The heart of the program sits in DelegateCommand.cs where I implement ICommand.

In his excellent article on ICommand John Papa describes 5 steps for Commanding in Silverlight, and I followed the five steps exactly to do the same in Windows Phone. What worked in Silverlight now works in the Phone.

John says, Step 1: Implement ICommand – that is,  implement the interface, which I do in the DelegateCommand class.

using System;
using System.Windows.Input;

namespace ICommandPhone
{
   public class DelegateCommand : ICommand
   {
      Func<object, bool> canExecute;
      Action<object> executeAction;
      bool canExecuteCache;

      public DelegateCommand( 
            Action<object> executeAction, 
            Func<object, bool> canExecute )
      {
         this.executeAction = executeAction;
         this.canExecute = canExecute;
      }

      public bool CanExecute( object parameter )
      {
         bool temp = canExecute( parameter );

         if ( canExecuteCache != temp )
         {
            canExecuteCache = temp;
            if ( CanExecuteChanged != null )
            {
               CanExecuteChanged( this, new EventArgs() );
            }
         }

         return canExecuteCache;
      }

      public event EventHandler CanExecuteChanged;

      public void Execute( object parameter )
      {
         executeAction( parameter );
      }
   }
}

 

Key here is that the Silverlight code works as is. In fact, that is true throughout this program.  The only changes for the phone have to do with layout on the MainPage.

The ViewModel class is named BookViewModel, which derives ViewModelBase, which, in turn, implements INotifyPropertyChanged.

Step 2 – Define the Command

In the ViewModel I define the ICommand that I’ll be implementing

public ICommand LoadBooksCommand { get; set; }

 

Step 3 – Create The Command

Again, I do this in the ViewModel, this time in the constructor.

LoadBooksCommand = new DelegateCommand( LoadBooks, CanLoadBooks );

 

While I’m in the constructor, I also mimic the creation of data that would normally be retrieved from, e.g., a web service,

public BookViewModel()
{
   Books = new ObservableCollection<Book>();

   AllBooks = new ObservableCollection<Book>();
   AllBooks.Add( new Book { ID = 1, Name = "Programming Rx and Linq" } );
   AllBooks.Add( new Book { ID = 2, Name = "Migrating Windows Phone" } );
   AllBooks.Add( new Book { ID = 3, Name = "Programming C#" } );
   AllBooks.Add( new Book { ID = 4, Name = "Learning C#" } );
   AllBooks.Add( new Book { ID = 5, Name = "Visual C# Notebook" } );
   AllBooks.Add( new Book { ID = 6, Name = "Learning VB.Net" } );
   AllBooks.Add( new Book { ID = 7, Name = "Programming .NET" } );
   AllBooks.Add( new Book { ID = 8, Name = "Programming ASP.NET" } );
   AllBooks.Add( new Book { ID = 9, Name = "TY C++ In 21 Days" } );
   AllBooks.Add( new Book { ID = 10, Name = "TY C++ In 24 Hours" } );
   AllBooks.Add( new Book { ID = 11, Name = "TY C++ In 10 Minutes" } );
   AllBooks.Add( new Book { ID = 12, Name = "Clouds To Code" } );
   AllBooks.Add( new Book { ID = 13, Name = "Beginning OOAD" } );
   AllBooks.Add( new Book { ID = 14, Name = "XML Web Classes From Scratch" } );
   AllBooks.Add( new Book { ID = 15, Name = "C++ From Scratch" } );
   AllBooks.Add( new Book { ID = 16, Name = "Web Classes Fronm Scratch" } );

   }

Step 4 – Create the VM

We are now ready to bind the Command property of the Button to the LoadBooksCommand shown above (which in turn, will invoke the LoadBooks method).  To do this, we must tell the View what its ViewModel is.  Still following John, I took the expedient of using a Resource in the View,

<phone:PhoneApplicationPage.Resources>
    <local:BookViewModel
       x:Key="vm" />
 </phone:PhoneApplicationPage.Resources>

 

I then set this ViewModel to be the DataContext for the StackPanel that holds the Button,

<StackPanel
   DataContext="{StaticResource vm}"

 

Step 5 – Bind the Command

Finally, in the button itself, I make the link to the LoadBooksCommand,

<Button
  Name="LoadButton"
  Content="Load"
  Margin="5"
  Command="{Binding LoadBooksCommand}" />

With that, when the button is pressed, the LoadBooksCommand is invoked through the ICommand mechansim, causing the LoadBooks method in the VM to be invoked,

private void LoadBooks( object param )
{
   string filter = param as string ?? string.Empty;
   Books.Clear();
   var query = from p in this.AllBooks
               where p.Name.ToLower().StartsWith( filter.ToLower() )
               select p;
   foreach ( var item in query )
   {
      this.Books.Add( item );
   }
}

As you can see from the illustration at the top of this posting, it works exactly as expected; the view contains a button, the codebehind for that view is empty, and we’ve bound the clicking of that button to the Command property in the View Model.

About Jesse Liberty

Jesse Liberty has three decades of experience writing and delivering software projects and is the author of 2 dozen books and a couple dozen online courses. His latest book, Building APIs with .NET will be released early in 2025. Liberty is a Senior SW Engineer for CNH and he was a Senior Technical Evangelist for Microsoft, a Distinguished Software Engineer for AT&T, a VP for Information Services for Citibank and a Software Architect for PBS. He is a Microsoft MVP.
This entry was posted in Data, Essentials, Mango, Mini-Tutorial, Patterns & Skills, WindowsPhone and tagged , . Bookmark the permalink.

2 Responses to Coming In Mango–ICommand

Comments are closed.