Using ICommand With MVVM Pattern

Scope
 
In this article, we'll show a basic ICommand interface implementation, to manage, in accordance with the MVVM pattern, the definition of UI-independent commands, realizing the typical View and Model separation, established by the pattern itself.
 
Introduction
 
As we have stated in a previous article (see Basic Outlines and Examples ON MVVM pattern), the MVVM fundamental paradigm is to maintain a separated application graphical part (typically, the part that presents data) from its business logic, or the modus, the code, through which the data is found, initialized and exposed. In the article linked above, we saw how to obtain that in relation to an object's properties, introducing an intermediate layer (the so-called ViewModel), that is responsible fro making data available (the Model's properties) to the View (the UI). We'll see here the same thing about the command, or how to overcome the event-driven logic (let's say, of a button, for example) to move toward a complete separation between the user-clickable object and the code that will be actually executed.

To this end, it will be appropriate to prepare a suitable environment, in other words a class, containing the data to be presented, an intermediate class for their presentation and a view that will be a WPF view in this case too.
 
A basic data class
 
As we've done in past examples, we'll start writing a simple class for our core data. In this case, the example will be very simple, designing an element that exposes two properties: a text, identified by a property named Text and a background, with a consistent property too. Beginning to hypothesize how to use a class like that, we could anticipate a binding to a TextBox, more precisely a mutual connection of their Text properties for the content and background for the background's color.
  1. Public Class ItemData    
  2.     Dim _text As String    
  3.     Dim _backg As Brush = Nothing    
  4.      
  5.     Public Property Text As String    
  6.         Get    
  7.             Return _text    
  8.         End Get    
  9.         Set(value As String)    
  10.             _text = value    
  11.         End Set    
  12.     End Property    
  13.      
  14.     Public Property Background As Brush    
  15.         Get    
  16.             Return _backg    
  17.         End Get    
  18.         Set(value As Brush)    
  19.             _backg = value    
  20.         End Set    
  21.     End Property    
  22.      
  23.     Public Sub New()    
  24.         _text = "RANDOM TEXT"    
  25.         _backg = New SolidColorBrush(Colors.Green)    
  26.     End Sub    
  27. End Class  
In its constructor, that class simply initializes its properties with the values of "RANDOM TEXT" for the Text property and a Green SolidColorBrush as the background. Looking torward its use, we know it will be appropriate, as said in the previous article, to set our View's DataContext. We must create a class that will work as a ViewModel, so that, given an ItemData, it will expose its fundamental properties (or, at least, those properties we really want to use in the operational area).

The ViewModel, first version
 
Let's start with a very small ViewModel, small enough for a DataContext initialization. Let's see a class to do that, with the functionality as a new ItemData creation and the exposure,  through properties, of the ItemData's properties. The fundamental core of any ViewModel is, as we saw, the INotifyPropertyChanged interface implementation, to trace properties modification, realizing an effective data binding.
  1. Imports System.ComponentModel    
  2.      
  3. Public Class ItemDataViewModel    
  4.     Implements INotifyPropertyChanged    
  5.      
  6.     Dim _item As New ItemData    
  7.      
  8.     Public Property Text As String    
  9.         Get    
  10.             Return _item.Text    
  11.         End Get    
  12.         Set(value As String)    
  13.             _item.Text = value    
  14.             NotifyPropertyChanged()    
  15.         End Set    
  16.     End Property    
  17.      
  18.     Public Property Background As Brush    
  19.         Get    
  20.             Return _item.Background    
  21.         End Get    
  22.         Set(value As Brush)    
  23.             _item.Background = value    
  24.             NotifyPropertyChanged("Background")    
  25.         End Set    
  26.     End Property    
  27.      
  28.     Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged    
  29.     Private Sub NotifyPropertyChanged(Optional propertyName As String = "")    
  30.         RaiseEvent PropertyChanged(MeNew PropertyChangedEventArgs(propertyName))    
  31.     End Sub    
  32. End Class    
In that class, we see the first step is made by creating a new instance of ItemData, calling its constructor. Its base properties will be initialized, as we saw above. We'll create then the properties apt to expose "sub-properties", in other words our data source properties. In this case, I've maintained for the ViewModel's properties the same name they possess in the base class. Through them, using Get/Set, the real data modification will take place.

The View, first version
 
Last, a basic View. As said, we'll make our ViewModel our window's DataContext. We'll put on the Windows a TextBox, binding it to the properties exposed by the ViewModel. We could write a thing like that:
  1. <Window x:Class="MainWindow"    
  2.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    
  3.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    
  4.     xmlns:local="clr-namespace:WpfApplication1"    
  5.     Title="MainWindow" Height="350" Width="525">    
  6.          
  7.     <Window.DataContext>    
  8.         <local:ItemDataViewModel/>    
  9.     </Window.DataContext>    
  10.          
  11.     <Grid>    
  12.         <TextBox HorizontalAlignment="Left" Height="25" Margin="30,53,0,0" Text="{Binding Text}" Background="{Binding Background}" VerticalAlignment="Top" Width="199"/>    
  13.     </Grid>    
  14. </Window>    
Please note the local namespace declaration, referencing the application itself. Without it, we won't be able to reference our ItemDataViewModel class as Window.DataContext, because it is defined in our project. Next, we set our TextBox bindings, on Text and Background properties. Source properties are, obviously, originated in our ViewModel. At this point, we have all we need to produce a first result. Even without executing our code, we'll see how the IDE shows us a window modified as we expect, thanks to the binding effect. Namely, a TextBox that contains the "RANDOM TEXT" text, on a Green background.
 
 
We now have a useful base to start speaking about commands.

ICommand Interface
 
The general scope of a command is to keep separated the semantics of the code from the object that will use it. On the one hand, then, we'll have a graphical representation of the command (in other words a Button, for example), while our ViewModel will host the real instruction set to be executed, when the developer's imposed conditions are met, when the user sends an input to the graphical command. In our example, we'll enrich our ViewModel with some sub-classes, to expose commands to bind them to the View. Nothing prevents though, if one prefers to do so, the creation of dedicated classes, referencing them in the view model.

The ICommand implementation resides on four fundamental elements: a constructor, CanExecute() and Execute() functions and the management of CanExecuteChanged event. Its most basic example could be expressed as follows:
  1. Public Class Command    
  2.      Implements ICommand    
  3.      
  4.      Private _action As Action    
  5.      
  6.      Sub New(action As action)    
  7.          _action = action    
  8.      End Sub    
  9.      
  10.      Public Function CanExecute(parameter As ObjectAs Boolean Implements ICommand.CanExecute    
  11.          Return True    
  12.      End Function    
  13.      
  14.      Public Event CanExecuteChanged(sender As Object, e As EventArgs) Implements ICommand.CanExecuteChanged    
  15.      
  16.      Public Sub Execute(parameter As ObjectImplements ICommand.Execute    
  17.          _action()    
  18.      End Sub    
  19. End Class  
We've defined a class named Command, implementing ICommand with its core elements. Action variables represents encapsulations of methods (Delegates). In other words, when we'll call our Command's constructor, we must tell it which sub or function it must invoke. To that end, we'll pass to it a reference to the desired Delegate. That reference will be executed on the Execute() method's calling. The CanExecute() method is useful to define when our command will be available to be executed. In our example, we'll always return True, since we want simply to have it always available. 

We have defined a basic implementation, we can now integrate it into our ViewModel. In our example, we assume we want to introduce a command through which we'll switch our element's background to Red. On our View, this function will be delegated to a button's click. We could modify our ViewModel as follows:
  1. Imports System.ComponentModel    
  2. Public Class ItemDataViewModel    
  3.     Implements INotifyPropertyChanged    
  4.      
  5.     Dim _item As New ItemData    
  6.      
  7.     Public Property Text As String    
  8.         Get    
  9.             Return _item.Text    
  10.         End Get    
  11.         Set(value As String)    
  12.             _item.Text = value    
  13.             NotifyPropertyChanged()    
  14.         End Set    
  15.     End Property    
  16.      
  17.     Public Property Background As Brush    
  18.         Get    
  19.             Return _item.Background    
  20.         End Get    
  21.         Set(value As Brush)    
  22.             _item.Background = value    
  23.             NotifyPropertyChanged("Background")    
  24.         End Set    
  25.     End Property    
  26.      
  27.     Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged    
  28.     Private Sub NotifyPropertyChanged(Optional propertyName As String = "")    
  29.         RaiseEvent PropertyChanged(MeNew PropertyChangedEventArgs(propertyName))    
  30.     End Sub    
  31.      
  32.     Dim _cmd As New Command(AddressOf MakeMeRed)    
  33.      
  34.     Public ReadOnly Property FammiRosso As ICommand    
  35.         Get    
  36.             Return _cmd    
  37.         End Get    
  38.     End Property    
  39.      
  40.     Private Sub MakeMeRed()    
  41.         Me.Background = New SolidColorBrush(Colors.Red)    
  42.     End Sub    
  43.      
  44.     Public Class Command    
  45.         Implements ICommand    
  46.      
  47.         Private _action As Action    
  48.      
  49.         Sub New(action As action)    
  50.             _action = action    
  51.         End Sub    
  52.      
  53.         Public Function CanExecute(parameter As ObjectAs Boolean Implements ICommand.CanExecute    
  54.             Return True    
  55.         End Function    
  56.      
  57.         Public Event CanExecuteChanged(sender As Object, e As EventArgs) Implements ICommand.CanExecuteChanged    
  58.      
  59.         Public Sub Execute(parameter As ObjectImplements ICommand.Execute    
  60.             _action()    
  61.         End Sub    
  62.     End Class    
  63. End Class    
Note how I've inserted the Command class as a subclass (that's not a required procedure, it is simply useful for me to present a less dispersive example). ViewModel declares a variable, _cmd, as a new Command, passing to it a delegate (AddressOf) for the previtare sub MakeMeRed. What does this sub do? Simply, as it can be seen, it takes the current object Background property (by which the same underlying ItemData property is exposed) and sets it as a Red Brush. As a MVVM rule, the command too must be exposed as a property. I've therefore created the FammiRosso property that exposes our Command externally from the ViewModel.

We could proceed with the introduction of our Command on the View. Le'ts modify our XAML as follows:
  1. <Window x:Class="MainWindow"    
  2.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    
  3.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    
  4.     xmlns:local="clr-namespace:WpfApplication1"    
  5.     Title="MainWindow" Height="350" Width="525">    
  6.          
  7.     <Window.DataContext>    
  8.         <local:ItemDataViewModel/>    
  9.     </Window.DataContext>    
  10.          
  11.     <Grid>    
  12.         <TextBox HorizontalAlignment="Left" Height="25" Margin="30,53,0,0" Text="{Binding Text}" Background="{Binding Background}" VerticalAlignment="Top" Width="199"/>    
  13.         <Button Content="Button" Command="{Binding FammiRosso}" HorizontalAlignment="Left" Height="29" Margin="30,99,0,0" VerticalAlignment="Top" Width="199"/>    
  14.     </Grid>    
  15. </Window>    
In a Button control, we can bind a command with the property Command. Note how fast a procedure like that is. Since our Window's DataContext is on ItemDataViewModel, we could simply write Command="{Binding FammiRosso} to bind the two. If we run now our example, we'll see initially a Green background TextBox, caused by the ItemData constructor. Clicking our Button will produce a change in the control's background as in the following:

It's important to emphasize, once again, the independence between the UI and the underlying logic. With the usual event-driven programming logic, we should have written our code in the window's code-behind, while, thanks to the MVVM, the files that define the UI can be maintained separately from the working logic, avoiding the necessity to modify the two of them in case we must change something in only one of them. (Unless that change takes place on a fundamental point of contact between the two, say a property name, for example. In that case, though, intervening for an adjustment will be much easier and faster.)

Parametrized Commands
 
In any scenario, a static command could not be sufficient to satisfy operational prequisites. Think about a command that must execute a different operation depending on another control's state. There's the need for a parameterized command. A command that can receive a UI's (or any other object's) data and, on that basis, execute several tasks.

In our example, we want to implement an additional button. That new button too will change our TextBox's background, but picking it from the user will write in the TextBox. The ItemData's Text property must be passed to our command as a parameter. The basic implementation of a parametrized command is not much different from what we saw above. We could summarize it as:
  1. Public Class ParamCommand    
  2.     Implements ICommand    
  3.      
  4.     Private _action As Action(Of String)    
  5.      
  6.     Sub New(action As Action(Of String))    
  7.         _action = action    
  8.     End Sub    
  9.      
  10.     Public Function CanExecute(parameter As ObjectAs Boolean Implements ICommand.CanExecute    
  11.        Return True    
  12.     End Function    
  13.      
  14.     Public Event CanExecuteChanged(sender As Object, e As EventArgs) Implements ICommand.CanExecuteChanged    
  15.      
  16.     Public Sub Execute(parameter As ObjectImplements ICommand.Execute    
  17.        _action(parameter.ToString)    
  18.     End Sub    
  19. End Class   
Please note the only difference from a previous implementation (aside from the class name) resides in the type specification for the Action delegate. We now have an Action(Of String), be it in the variable declaration, and obviously in the constructor and in the execution syntax of the Execute() method. Namely, we declare a delegate of any type we wish (I chose a String and that will be evident shortly) that will reference a method with the same signature.

Like the previous example, we need the implementation of our Command to be made in our ItemDataViewModel, exposing it through a property. Adding our parametrized command's class to the ViewModel, we'll have:
  1. Imports System.ComponentModel    
  2.      
  3. Public Class ItemDataViewModel    
  4.     Implements INotifyPropertyChanged    
  5.      
  6.     Dim _item As New ItemData    
  7.      
  8.     Public Property Text As String    
  9.         Get    
  10.             Return _item.Text    
  11.         End Get    
  12.         Set(value As String)    
  13.             _item.Text = value    
  14.             NotifyPropertyChanged()    
  15.         End Set    
  16.     End Property    
  17.      
  18.     Public Property Background As Brush    
  19.         Get    
  20.             Return _item.Background    
  21.         End Get    
  22.         Set(value As Brush)    
  23.             _item.Background = value    
  24.             NotifyPropertyChanged("Background")    
  25.         End Set    
  26.     End Property    
  27.      
  28.     Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged    
  29.     Private Sub NotifyPropertyChanged(Optional propertyName As String = "")    
  30.         RaiseEvent PropertyChanged(MeNew PropertyChangedEventArgs(propertyName))    
  31.     End Sub    
  32.      
  33.     Dim _cmd As New Command(AddressOf MakeMeRed)    
  34.     Dim _cmdP As New ParamCommand(AddressOf EmitMessage)    
  35.      
  36.     Public ReadOnly Property FammiRosso As ICommand    
  37.         Get    
  38.             Return _cmd    
  39.         End Get    
  40.     End Property    
  41.      
  42.     Public ReadOnly Property Message As ICommand    
  43.         Get    
  44.             Return _cmdP    
  45.         End Get    
  46.     End Property    
  47.      
  48.     Private Sub MakeMeRed()    
  49.         Me.Background = New SolidColorBrush(Colors.Red)    
  50.     End Sub    
  51.      
  52.     Private Sub EmitMessage(message As String)    
  53.         Try    
  54.             Me.Background = New SolidColorBrush(CType(ColorConverter.ConvertFromString(message), Color))    
  55.         Catch    
  56.             MakeMeRed()    
  57.         End Try    
  58.         MessageBox.Show(message)    
  59.     End Sub    
  60.      
  61.     Public Class Command    
  62.         Implements ICommand    
  63.      
  64.         Private _action As Action    
  65.      
  66.         Sub New(action As action)    
  67.             _action = action    
  68.         End Sub    
  69.      
  70.         Public Function CanExecute(parameter As ObjectAs Boolean Implements ICommand.CanExecute    
  71.             Return True    
  72.         End Function    
  73.      
  74.         Public Event CanExecuteChanged(sender As Object, e As EventArgs) Implements ICommand.CanExecuteChanged    
  75.      
  76.         Public Sub Execute(parameter As ObjectImplements ICommand.Execute    
  77.             _action()    
  78.         End Sub    
  79.     End Class    
  80.      
  81.     Public Class ParamCommand    
  82.         Implements ICommand    
  83.      
  84.         Private _action As Action(Of String)    
  85.      
  86.         Sub New(action As Action(Of String))    
  87.             _action = action    
  88.         End Sub    
  89.      
  90.         Public Function CanExecute(parameter As ObjectAs Boolean Implements ICommand.CanExecute    
  91.             Return True    
  92.         End Function    
  93.      
  94.         Public Event CanExecuteChanged(sender As Object, e As EventArgs) Implements ICommand.CanExecuteChanged    
  95.      
  96.         Public Sub Execute(parameter As ObjectImplements ICommand.Execute    
  97.             _action(parameter.ToString)    
  98.         End Sub    
  99.     End Class    
Please note the ParamCommand declaration, the declaration of the _cmd variable and the reference to the EmitMessage delegate, a subroutine that receives an argument of String type. That routine will try to convert the argument in a color, to make a brush from it and assign it to the ItemData's Background property. At the same time, it will pop up a MessageBox, containing the passed String argument. We'll expose our Command through the Message property. Now it must be clear that the argument to be passed to the routine must, to meet the ends we intend, the exposed Text property, making it to be typed by the user, received from the parametrized command and used in the delegate routine's context.

To realize a bind like that, we implement a new Button on our View. It's final XAML will become:
  1. <Window x:Class="MainWindow"    
  2.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    
  3.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    
  4.     xmlns:local="clr-namespace:WpfApplication1"    
  5.     Title="MainWindow" Height="350" Width="525">    
  6.          
  7.     <Window.DataContext>    
  8.         <local:ItemDataViewModel/>    
  9.     </Window.DataContext>    
  10.          
  11.     <Grid>           
  12.         <TextBox HorizontalAlignment="Left" Height="25" Margin="30,53,0,0" Text="{Binding Text}" Background="{Binding Background}" VerticalAlignment="Top" Width="199"/>    
  13.         <Button Content="Button"  Command="{Binding FammiRosso}" HorizontalAlignment="Left" Height="29" Margin="30,99,0,0" VerticalAlignment="Top" Width="199"/>    
  14.         <Button Content="Button" Command="{Binding Message}" CommandParameter="{Binding Text}" HorizontalAlignment="Left" Margin="30,133,0,0" VerticalAlignment="Top" Width="199" Height="29"/>    
  15.     </Grid>    
  16. </Window>  
Note that, as previously, the command-exposing property is bound on the Button's Command property. To pass our argument, it will be sufficient to set the CommandParameter property on the Button, with a reference at the property to link/bind. In our case, CommandParameter="{Binding Text}" specifies that the argument to be passed to our command must be found in the bound property Text.

Running our code again, we could type various strings into our TextBox (from the System.Windows.Media.Colors class, namely Red, Black, Green and so on), clicking each time our button and seeing how the TextBox's Background property will be modified (and the MessageBox shown, too). In case the user types an invalid input, as we can see in the EmitMessage() code, the imposed color will be Red.