207 – Commands

Command versus Event

No this is not the next grudge match on Mixed Martial Arts… Or the Grammy Awards. If you’ve done any coding at all you know what an Event is. They are pre-wired into all the UI elements you use: Like Button.Click or TextBox.TextChanged. Certainly you’ve also created your own events for your applications: C# is an event-driven, Object-Oriented language after all. If you haven’t created your own events there is a great tutorial over on DreamInCode.net as part of their Learning C# Series. If you don’t yet grasp Objects and Classes they have a tutorial for that too. If you’re just starting out in C# you should probably take the time to work through that series so you get a foundation under you before going much further.

When to use each.

The thing about UI element events is… They are meant to be handled at a UI level but many people try to make them something that gets handled in the ViewModel. Don’t be one of those people. UI element event is for UI level handling. If you do something with Button.Click it belongs in the code-behind of that UI (Page or View).

Let’s say you want to take what you learned in the previous lesson about reusable controls to make a customized Entry that… ah… takes only IP addresses with the typical formatting: for example. In that case it might be pretty quick and easy to handle the .TextChanged event of the Entry so you can qualify each character as its entered. After all, at this level you’re dealing with UI, you care about the UI of things, there is no ViewModel, and everything you’re doing is encapsulated within your IPv4input control.

However, if you’re on a page and you want to put a button on the page for… say… I don’t know… Submit form… or Save Changes… Or you are making your own header bar and need a Back button. That isn’t a UI related function, is it? ‘Save changes’ is an instruction to the ViewModel to perform some action. If you tap your Back button you are ordering the app to do navigation. You are giving it a command to do something.

You’ve done this myButton.Click += TheMethodToExecute();
This is a subscription. This subscribes a method to the event. But this means you have to know at design-time what method you want to execute when that button is clicked. There’s the problem with using this for MVVM where the UI doesn’t know about the ViewModel or its methods. Events are limited to one operational context which is generally their own code-behind.

Commands are more… fluid. A command can be assigned and handled with the BindingContext that your View is using at the moment. Change the context, change the handler for the command. Or re-assign the command at run-time.

Make sense? It’s the difference between yelling out a command “Switch to the red brush” not knowing who is supposed to handle it or how, and reaching in to a specific class a can executing the SwitchBrush(Red); method. Because of this ‘just shout it out to whomever is listening’ concept commands are great for multiple ways to activate the same thing. Have you ever noticed how most programs have multiple ways of doing the same thing? If you want to close and save an open document you can choose close from a menu, click the ‘X’ widget on the document window, close the app itself, make a left-to-right swipe gesture, right-click the tab in a multi-tabbed UI… and the list of possibilities goes on. You don’t want to have every one of those options hardwired to a specific method on a specific class. Commands are not so tightly coupled. You really just say “this button raises the CloseCommand” without being tightly tied to any class or method. Leaving your app free to do things like: “This menu calls CloseCommand“, “This button calls CloseCommand“, “This gesture calls CloseCommand etc. Then worry about the actual CloseCommand separately. It’s that buzzword: Separation of Responsibilities

Commands also have one other completely awesome feature: They understand the concept of CanExecute – and that can affect the IsEnabled of a UI control. I’m going to repeat that because it’s a huge feature that everyone seems to miss, not know about, or otherwise just ignore. When the command CanExecute is true all the buttons and menus that are tied to the command are automatically enabled. When the command CanExecute is false all the UI elements are automatically disabled. Let me give you an example and I’m sure you’ve seen this in other apps. Let’s say you are filling out the new user profile form on a page. You have to provide an alias as well as your real name and an email address. At the bottom is the [Submit] button. Notice the submit button is always disabled until you have filled in all the fields on the form. That’s because the button is wired to the SubmitFormCommand, and it has a SubmitFormCommandCanExecute method checking to see if you’ve finished all the requirements. Once you have that CanExecute will return true and the button will magically become enabled all by itself: You do not have to go around micromanaging the IsEnabled state of your button… and the corresponding menu item that does the same thing… and the flick gesture… and the Siri command… You don’t have to micro-manage the .IsEnabled of all those buttons and menus and gestures and keystroke shortcuts if you use commands correctly. Do I have your attention now?

In our PetsViewModel.cs lets create a command for adding a new pet to the Pets collection. This is one of those times where the code does most of the talking:

  1. Add a property for the ICommand
  2. Add a handler for when the Command is exectuted
  3. Add a line assigning a value to the property, that specifies the handler method

In its simplest forms, that’s all there is to a Command. And through the magic of Binding, our UI will update itself automatically: There is no code here that micromanages the UI. If it sounds like I’m harping on this it’s because I am. It can’t be over-stressed that your ViewModels should know nothing about the UI: Its not their role in life.

We have a command. Great. How do we use it? Go back to MainPage.xaml. Find the Grid. Right now Row 0, Column 0 contains the ListView with our Pets. We want to add a button above that to be our New Pet button. There’s a number of ways to do it that are all equally right. This is where your personal style comes in. My choice is to wrap the ListView in a StackLayout, then put the button at the top of the stack. Leaving the StackLayout as the contents of the first column. When you’re done with these changes your MainPage should look like this:

We aren’t changing any of the ListView.ItemTemplate, so I’ve collapsed that for clarity. All you’re doing is wrapping the ListView in a StackLayout, and putting a Button at the top.

Here’s the big take away with this XAML – Notice the button. It does NOT specify what method to execute when it is clicked. Its just raising the command to do something, not micromanaging how to do it. Or where to do it. If you change ViewModels that this UI is binded to at run-time then the command will be run from whatever assignment was made on that ViewModel: Something you can’t do with events.

Let’s take this a step further and create a DeletePetCommand that will take a CommandParameter of the actual Pet to be deleted. We’ll add a delete button to our ListView.ItemTemplate so the user can just tap Delete on the Pet they want to remove. That’s a fairly common use case. Here is what we’re aiming for. Notice the new Delete button on each ListView item.

Adding the new Command to the PetsViewModel.cs shouldn’t look new to you now. Make the property, the method handler then assign them in the constructor.

Flip back to MainPage.xaml. Scroll down to the ViewCell, where we have a StackLayout for properties. Add a Button as the last time in the StackLayout. We’re going to set it to place at the end and expand its space to fill in any empty space. None of that is mysterious.

What does look just a bit interesting is the binding for the button. Sometimes people get confused trying to work out the binding context for each ‘layer’ so we’ll walk through it.

Here’s what’s happening. The button Command is coming from the ViewModel. When you tap the button its going to raise the DeletePetCommand on the ViewModel. That command takes a CommandParameter. Look at the On_DeletePetCommand(object obj) method signature. That parameter is going to receive the CommandParameter we’re passing. We get that from the {Binding .} which is Xamarin syntax for “this element from the collection used as the Source on the ListView.” Your ListView takes a collection of 3 pets. This template is reused for each element. If you click the button on the 2nd item, the CommandParameter with be the actual 2nd item from the collection.

Then what happens when we tap the button?

  • The Pet comes in as the obj parameter.
  • We cast it from a generic object type, to a Pet type.
  • Then we check to make sure it isn’t null (just to be robust and safe), and we check that the Pet being passed to the method is really part of our Pets collection. Again, to be robust and safe. Its easy to imagine 6 months from now when there are 3 other members on your team and someone calls this method from someplace other than the ListView. That’s the point of commands after all, to not be hard coded to just one method of execution. To be safe, we make sure its not null, really is a Pet object type, and really is in our collection.
  • If it passes all those safety checks, then we remove it from the Pets collection. Again, any UI binded to the collection will update automagically.

Hit [F5] and give it a play. Add a new Pet, change its name, delete it, delete an existing pet out of the middle of the List. Cool eh?