Revisiting Commands

Having put together the basics of the user interface for my current project I decided to do some more reading regarding the best practices around using a Command Pattern in WPF.

Specifically this means determining how to use the ICommand and RoutedCommand. My previous attempt (without reading any of the documentation) was something of a failure but I pretty much have the same goals in mind:

  1. UI elements that perform an action that is not purely UI related are required to be bound to a Command. This must be easily done in XAML.
  2. The Window/Page itself should have minimal (i.e. as close to possible to zero) code in the code behind. This means no ugly event handlers.
  3. The Command or more likely the Command Binding mechanism will be responsible for setting attributes on the associated UI element(s). So this includes things like Text, Image, Tooltip, Enabled, Visible etc.

The closest thing I’ve found so far in terms of recommended approaches is the collection of blog entries written by Dan Crevier back in 2006. Dan does a great job of discussing a simplified version of the Data Model – View – View Model (DV-V-VM) that the team working on Microsoft Max used. Having said that there are some approaches that he takes that I either find too unwieldy (one command per class) or (just as likely) don’t fully comprehend.

Reading straight out of the MSDN documentation I stared with:

    <Page.CommandBindings>
        <CommandBinding Command="{x:Static pages:RibbonTest.WriteEntryCommand}" 
Executed
="CommandBinding_Executed"
CanExecute
="CommandBinding_CanExecute"/>
</Page.CommandBindings>
...
<Button Command="pages:RibbonTest.WriteEntryCommand"/>

This involved defining my own RoutedCommand on the page itself (pages:RibbonTest) and then binding the Executed and CanExecute events to event handlers on the page. Of course this doesn’t meet any of my three requirements, – it’s too much XAML, it requires code behind event handlers and with the exception of the Enabled property doesn’t “reflect” command properties to the UI element.

Needless to say I went through a whole raft of possible solutions from here (refer to references below), trying each in turn to see what worked for me and what didn’t.

At the moment I have created an attached dependency property (as per Dan’s post) so that my XAML is nice and concise.

<TabControl Name="tabControl2" Style="{StaticResource RibbonBarStyle}">
    <TabItem Header="Holidays">
        <ToolBarTray>
            <ToolBar Header="Select a Holiday">
                <Button commands:CommandBinder.Command="{Binding Controller.NewHoliday}"/>
                <Button commands:CommandBinder.Command="{Binding Controller.OpenHoliday}"/>
</ToolBar>
        </ToolBarTray>
    </TabItem>
...


</TabControl>

The Controller referenced above is instantiated by the form and defines all of the commands available for the form. It is also responsible for keeping the form state which is then reflected in the commands, and thus by the buttons. The commands are actually a custom class (UICommand) that is a “wrapper” around a RoutedCommand and contains other metadata that is associated with the command. This includes the caption text, full description, image, IsEnabled and IsAvailable (visible/security). The wrapped RoutedCommand also defines any keyboard gestures.

Taking this approach means that:

  1. Only the attached property needs to be set – the CommandBindings are not required – this is done automatically by the attached property.
  2. The command execution logic (callback) lives either in the controller, or in a UICommand derivative (for common functions like navigation).
  3. The only code required in the form code-behind is the instantiation of the controller. Of course this could easily be done in XAML too if preferred.
  4. In addition to setting the Text (via binding), Enabled and Visibility properties I’m also using the CommandBinder to build a groovy Tooltip complete with input key shortcuts.

XAML Ribbon with Tooltip

Of course its not all roses – there are more than a couple of “nasty” bits in my implementation at the moment. One surprising one was an oddity in the ICommandSource interface. Within the CommandBinder attached property I thought to use this interface to set the Command property on the source at the same time as I registered the RoutedCommand. However, it turns out that the ICommandSource.Command property is read-only – most frustrating.

More than anything though I’m curious as to how everyone else tackles implementing a command pattern (and MVC/MVP etc.) in WPF?

References:

WPF Commands on Code Project

Karl on WPF

Rob Relyea on ICommand, RoutedCommand and RoutedUICommand

Josh Smith on RoutedCommand

Josh Smith on MVC

Commands in Prism (some great comments)