My .Net Adventure

Provider Based Commands

To access the code discussed in this post click here. Feel free to do what you want with it. Though no warranty for you.

Commanding is a pretty amazing thing, and in WPF it is about as good as it gets. But as with all things cool, design decisions need to be made when considering their usage in an application. One such decision that I have had to make several times is how to best deal with core application commands such as the SaveCommandand CloseCommand. These global application commands are particularly tricky for a few reasons. First, you must ensure consistent behavior throughout the entire application. It is important that users do not have to relearn these commands on each screen the navigate to. Secondly and equally important, the development experience must be simple enough that the first point can be realized. These type of application commands all share three important traits.

Accessible– Commands must be accessible in consistent way across your application

Predictable – Commands must behave in a predictable way across the application when executed

Contextual– Commands must be able to consider application context

Over time I have started to use the term Contextual Commands when describing these types of commands. In this post I will outline the approach that I have used with success on a few different projects as well as provide a simple reference implementation. But before that, let us outline what each of the three traits listed above mean.

Accessible

Accessibility is a primary trait that Contextual Commands must have. This simply means that commands are presented to the user and executed by the user in a similar fashion throughout the entire application. A good example of this is how Microsoft Word handles the Save command. Several consistent options exists.

Control + S

The Save button on the tool bar

The Save menu item on the Ribbon application menu

In fact users have become so conditioned to this commands that many will hit control+s as part of their normal key press behavior, allowing them to save their work as they go.

To accomplish Accessibility in a developer friendly way I choose to make all contextual commands singletons. (Take a deep breath, I know, I know). Utilizing the Singleton Pattern in this case frees developers from the pain of creating instances, command bindings, and all the other error prone work that would need to be done otherwise. Making Contextual Commands singletons allows us to expose commands in multiple ways while ensuring the basic buildup of a command will remain consistent. In short all visualizations of a Contextual Command use the same instance limiting its possible variation that could hurt overall usability.

Predictable

Predictability means that aside from contextual differences, the execution of a command will behave in the same way every time it is executed. For example if you decide the Save button will be disabled until a view is dirty that choice should hold true throughout all views. If you decide that your close command is going to prompt users for unsaved changes we need to make sure it always does. There should be no variation in overall experience of using these commands. Holding to the standard of predictability will ensure that developers need not worry about such choices preventing them from mucking up your beautiful framework code.

To accomplish Predictablility base implementations of each command will be provided. Using a combination of the Tempalate Method and Provider Pattern we can open the implementation of the command enough to developers so contextual differences can be supported yet at the same time closing off its core implementation ensuring its execution is predictable every time. Textbook Open Closed Principle.

Contextual

The last and most important point is that these commands must consider the current context of the application. For example clicking the save button in Microsoft Word it saves the document that is currently in view. This may seem simple, but often times this simple concept turns into some very nasty error prone code. Think about what it means to save a document. To save the document correctly there are several things that need to be considered. Is the file readonly? Is the file on a network share? Is the file in collaboration mode? Is the file a word document? Is it a html document? All of these decisions are contextual in nature and will likely differ on each view in an application.

Gathering enough context to correctly save something can often times be a lot of work. Using the Provider Pattern helps us keep this code encapsulated and clean. Each view/control will have a chance to provide to the commands the contextual details needed to handle the difference present in each view.

Disclaimer

As usual, the reference implementation I am providing here is illustrative at best. There are many things that should be done differently in a real application.

The Commands and Provider

A few months ago I posted my flavor of the RelayCommand . RelayCommand is a simpleimplementation of the ICommand interface adding to it support for asynchronous processing, Predicates and Actions, as well BusyCursor support. Also for simplicity I usually group all Contextual Commands in a single class called ContextualCommands. If you prefer a more granular approach you could split this class apart into several separate classes, I will leave that up to you . Lets take a quick look at components needed to support the implementation. The image blow shows the core components of our the setup.

The IContextualCommands interface simply defines the commands I consider contextual (CloseCommand, SaveCommand). In addition to defining the commands this interface defines the SetProvider method. This method gives consumers the ability to change the command provider that is used for each of the command implementations. In the end it is the SetProviderthatallows individual views to provide the contextual information needed by the commands. The SetProvidermethod will work with the IContextualCommandsProviderinterface.

IContextualCommand Interface

The IContextualCommandsProvider interface defines the methods each provider must implement. Since I have lumped the ContextualCommands into a single class the provider must provide the details for each command. The implementation provided by the provider will be used during command execution this is the key to supplying contextual differences from view to view.

Contextual Commands

The ContextualCommands class is the single implementation of the IContextualCommands interface and is registered with Unity as a singleton. This class exposes the Contextual Commands to the rest of the application. This class does a few important things for us.

Usage

With the basic components built out a discussion about their usage may be helpful before you look at the example code. Since the ContextualCommands class is a singleton the only moving part is the underlying provider implementation. Generally speaking the ContextualCommands class is supplied with a new provider each time a view is presented. In the example code you will notice I include a simple Controller object. This class is responsible for presenting views into the MainRegion of our application. Essentially when the Controller class is asked to present a view the following things happen.

The Controller first asks Unity to create our View

The Controller looks to see if the resolved View has a ViewModel that implements the IContextualCommandsProvider interface

If the View’s ViewModel implements the IContextualCommandsProvider interface, the Controller calls the SetProvider method on the ContextualCommands instance passing to it the the IContextualCommandsProvider implementation

Here is a quick look at the Controller class, again please look at the supplied example code for additional details about this implementation.

In short, every time a view is presented that view becomes the provider to the ContextualCommands.

The Null Provider

In real life not all ViewModels would implement the IContextualCommandsProvider interface. This puts us in a tricky position when the current ViewModel implements the interface, and the ViewModel we are navigating to does not. Since the new ViewModel is not a provider the Controller will not call the SetProvider as a result the last ViewModel will remain the provider. This can lead to memory leaks, and all sorts of strange things. To get around the disconnect the SetProvider method allow nulls to be passed in. This essentially disables all of the ContextualCommands. This problem would best be solved with the creation of a NullProvider type but for simplicity I have ignored that fact.

Sample Application

I created a very small sample implementation of this concept. To download it click here. This application contains the following things.

A very brief and limited MVVM Framework, simply used to illustrate how these commands may be used

The ContextualCommands implementation

Unity support to manage the moving parts

A RelayCommand implementation

A BusyCursor implementation

Please feel free to download the code and sort through all the details yourself, my intent with this post is simply to introduce the concept of Provider Based Commands. I hope the example code is clear enough to show you the power of this approach. I can tell you from personal experience, every time I go to a new client this is one of the first things I implement. And time and time again, I am happy I did it this way.

Interesting find. However I am unable to reproduce this locally. It seems to be working for me. Could you send me a sample view model that has the issue? Perhaps it has something to do with the expression you are passing to the call to RaisePropertyChanged. Here is an example of something that works for me.

It turns out that lamdas on value types using the Action delegate as I had it set up, are converted to UnaryExpression objects. And of course I was attempting to down cast to a MemberExpression. Your changes are the way to go. I have uploaded the modified source code. Thanks very much for pointing this out.