Description

We’ve already discussed several facets of the Model-View-ViewModel design pattern, or rather MVVM. In this lesson I want to add one more piece to the puzzle so that we can employ it in our upcoming project.

MVVM provides a clean separation of concerns between the data model and the view. This is accomplished through the ViewModel class which is responsible for publishing methods that return collections of our data model to the view so that the view can bind to it and display it.

That covers the *display* of data.

What if, for example, we want to not only bind data in our view, but also bind the Click event of a button to a method defined on our data model?

Commands allow us to do that.

It is easier to show you what I mean than to explain it in theory without a concrete example in front of you.

I’ll create an app that might be used to check in cars at a Car rental company. Customers drop off their cars in an airport, the Car rental employee sees a list of cars scheduled to be returned today, they click a button next to the car that they receive and see a message with the check in time. This is far from a complete example, but it will allow us to see a simple example of Commands in action.

I’ll start by creating a new project called “BindingToCommands”. I’ll immediate add a Car class:

Note: Ideally we would store CheckedInDateTime as a DateTime, not a string. I did this because I want to format the string nicely. As you’ll learn in the next lesson, we can create a ValueConverter for the purpose of formatting the date nicely while keeping the value as a DateTime.

With the preliminary work out of the way, we can turn our focus to implementing the Command. The first order of business is to implement the command that represents a “check in” for a car. I’ll create a class called CheckInButtonClick that implements ICommand. Then, I’ll use the Control + [dot] keyboard combination to implement the ICommand interface:

This provides a stubbed out set of methods and the event declaration like so:

First, I need to merely answer the question “can this be executed”? Here I could write logic to decide whether or not this command can be executed based on the current state of the Car object that is passed in as a parameter. Ultimately, I’ll return a bool. In our case, since I’m going to keep this simple, I’ll merely return true. This command can always be executed regardless of the state of the object.

In actuality, I would probably want to check to see whether if this instance of Car has already been checked in prior to allowing it a second time. I’ll leave the implementation of that business rule to you for experimentation.

Now, I need to associate the command with my Car class:

public ICommand CheckedInCommand { get; set; }

public Car() { CheckedInCommand = new CheckInButtonClick(); }

I create an auto-implemented property of type ICommand, then in the Constructor, set the property to an instance of the CheckInButtonClick() command class. Now I have a class that can be Commanded, in other words, that I can bind a Command to it.

Next, I’ll want to tell the command what to do when this command is executed? That’s what we’ll do in the Execute method. In this case I want to set the CheckedInDateTime property to DateTime.Now. Also, per my note, above, I want to format that for proper display.

I have two options. I can either implement this in my model (i.e., a public method on my Car class) or the classes I use to generate by View Model (i.e., the CarDataSource class). Which one you choose depends on how accessible you want to make your View Model and how flexible you want to make your Command. If you were to either make your Data Source a property of the App OR make all the methods of your Data Source class static, AND you don’t mind your Command being tied specifically to your CarDataSource class, then you could implement the Execute command like so:

However, this approach has one obvious downside. The Command is now coupled to the CarDataSource. It could not be used as a more general purpose command. That might be fine for your purpose, however another option is to make the CheckInCar() method a public property of the Car class itself:

Next, I’ll need to wire up the binding correctly. I will want to fire the Command when I click the button, AND I’ll want to pass in the current instance of the Car to the Command’s Execute() method. To do this, I’ll add the following XAML in the Button’s declaration:

To me, this is a bit confusing. It looks like I’m binding the ENTIRE CarViewModel to the CommandParameter. However, the correct way to interpret this … the ListView’s ItemSource expects a collection. Then each item is then bound to just one instance of that collection, therefore the CommandParameter=”{Binding}” means “bind to the current instance of the Car class”, not to the entire collection. That was a little tricky for me to understand at first. The key is understanding how the DataContext flows down from the page, into the ListView and then into the ItemTemplate.

Unfortunately, when I run the app, I may not get the results I was hoping for visually. I would expect the value of CheckedInDateTime to change and then be presented on the screen when I click the Check In button. It does not. I assure you, the value is being changed in the data model, but because Car is not notifying the user interface of this property change, the user interface does not know it should update it’s presentation of the data.

Do you recall what we need to do to tell the user interface that a property changed?

Yes, we need to implement the INotifyPropertyChanged interface on the Car class, then in the CheckedInDateTime setter, call the NotifyPropertyChanged() method that the interface forces us to implement. Let’s implement that now using the Control + [dot] technique from earlier.

Note: Keep in mind that this is not part of Commands per se, however if your Commands will be updating properties, you very well may need to implement INotifyPropertyChanged to enable some user interface update like we’ll do from this point on in the lesson.

Now when I click the Check In button, you can see the update in the user interface:

Recap

The beauty of a Command is that it keeps the separation of concerns in tact while allowing you to handle events triggered on the user interface that affect an instance of your view model. We talked about the implementation of the ICommand interface and walked through a complete example. We also looked at a practical implementation of the INotifyPropertyChanged interface.

The Discussion

While I see the use of Command objects instead of the Click event for the button in MainPage.xaml in order to keep the View and ViewModel decoupled, does that mean the Click event is pretty much obsolete when it comes to developing apps using the MVVM pattern?

@ryanthtra:i don't think its obsolete, we can make use off command like this only when we bind our control and when we are changing data in viewmodel, we cant even access the button object or other page objects in viewmodel.