MVVM Part 4: Commanding

Note: This posting is part of a series. See MVVM-Library for other parts and download.

Commanding is a very important topic in MVVM applications as it represents – together with Data Binding – the only mode of interaction between ViewModel and View.

Predefined Commands

In WPF there are three predefined commands:

Class Diagram: Predefined Commands in WPF

However, there is one problem: While ICommand encapsulates a “real” command that knows what to do itself, RoutedCommand and RoutedUICommand are dependant on the logical tree. Routing through the element tree, they look for a command binding which then invokes a method containing the actual implementation / logic.

So they are used totally different. Routed(UI)Commands are normally supplied as static fields or properties. ApplicationCommands is one example: The command declared there come with no logic; the addressee has to provide it.

Josh Smith’s Solution

Almost one year ago, Josh Smith published the article Using RoutedCommands with a ViewModel in WPF on Code Project (I recommend you reading through it).

In short: He introduced an easy way how to use RoutedCommands from within the ViewModel without connecting it to strong to the UI. He was able to do so by writing his own CommandBinding class. Unlike than many other people he did not write classes implementing ICommand and made them available in the ViewModel.

At this point: Many thanks to him for this really great article!!!

Why do I mention him and his article here? Well, my commanding solution is based on some of his ideas. Although I rewrote lots of his code you’ll still find some of the original code in my project.

My solution

The main players are the same – the members changed a bit:

Class diagram: My Solution

Note: VS seems to have problems with displaying delegates in class diagrams. The correct signature for CommandSink.RegisterCommand is “CommandSink.RegisterCommand(RoutedCommand command, Func<object, CommandState> getCommandStateCallback, Action<object> executeCallback)”.

CommandState

There was one main thing, I changed: Instead of providing a method CanExecute, I introduced GetCommandState which returns a new object, a CommandState.

What is a CommandState?

A command state gives information about the state a ViewModel has affecting the way of executing a command.

That may include:

  • If the command can be executed
  • Why a command can not be executed
  • What the execution of the command will change
  • Any warnings a user should notice before doing something

As the first point is essential, CommandState includes CanExecute which indicates exactly this. There are also two (non-abstract) subclasses ExecutableCommandState and NotExecutableCommandState which allow you using CommandStates without writing subclasses.

However, the other points can only be covered with custom inheritors of CommandState.

Why using CommandStates?

CommandStates help you implementing a very important factor for usability: dynamic feedback.

The UI informs the user, what will happen if he clicks on button a. In opposite to static tooltips which have to handle multiple cases, you build your tooltips dynamically and integrate the status information you get from a CommandState. You even can show why an action can not be done.

How should a CommandState look like?

In order to allow different UIs for your ViewModel classes, you should use almost no formatted data. That means: Work with enumerations, bools, … and collections of them.

As CommandState is derived from ViewModelBase, there are nearly unlimited possibilities to present the data to the user. (Note: A later posting will introduce some kind of factory for views that makes this process much easier again).

The sample project does it wrong: It uses one CommandState for everything that is only different in its message. Why am I not using multiple CommandStates then? Well, it’s not only the “ViewFactory” I did not introduce yet. I had to decide: Introduce them all in this article or writing that workaround. I chose the second. You’ll see later, why you should use them in this case :-)

CommandSinkCommand

I already mentioned that my solution relies on “implementation-less” RoutedCommands.

In some cases, however, it isn’t possible to use them (especially when the command would never reach its target).

In order to be prepared to situations like these, CommandSinkCommand represents a routing-independent ICommand – you don’t have to write your code twice.

CommandingViewModel

CommandingViewModel implements ICommandSink (and of course ViewModelBase). Because of that it is able to be the target of routed commands.

How to declare and register your own commands?

I have written two snippets for that (“command” and “regCommand”). The sample project shows how commands are correctly declared and registered.

CommandStateExtension

CommandStateExtension simplifies evaluating the state of a command connected to a specific control. As the sample project contains an example for that, too, I won’t explain its usage further.

Sample Project

Screenshot of teh sample application Take a look at the screenshot on the left:

My sample project today is a simple counter where the buttons communicate with the ViewModel using RoutedCommands.

In additions there are labels indicating the “status” of each command.

Download it from MVVM-Library.

About these ads
Follow

Get every new post delivered to your Inbox.

%d bloggers like this: