[MVVMbasics] New version 2.0 features #5: Event Binding

[notice]All blog posts with a title that starts with [MVVMbasics] are related to the MVVMbasics framework. If you are only interested in my regular blog posts and not in MVVMbasics, ignore these. To list all articles covering MVVMbasics, go to http://mvvmbasics.mobilemotion.eu/documentation![/notice]

Binding events directly to commands

This is a widely discussed topic among developers: Most XAML controls allow Command Binding, which means that a custom command (defined in the Viewmodel) is invoked as soon as a specific event is raised on that control. For example, a command binding to a button’s Command property will be invoked when the button’s Click or Tap event fires. However, in some cases you’d want to react to different events – an usually end up with event handler methods in the View’s code-behind that do nothing more than call one of the Viewmodel’s commands. Code that works but smells: violating the MVVM pattern, being complex to read and maintain,and resulting in redundant code parts in cross-platform projects.

Unfortunately, in spite of the improvements brought by .NET 4.5, there is still no real platform-independent solution for this problem. (By the way, I’m planning a separate series of blog articles on this dilemma, for all those who are interested in the technical backgrounds!)

If you’re developing only for WPF (.NET 4.5) or the Silverlight 5 platform, you might be interested in taking a look at my EventBinding Library. For all other use-cases (especially App projects targeting multiple platforms!), I decided to integrate a somewhat unconventional workaround in version 2.0 of the MVVMbasics framework. This approach does not solve all of the problems concerning event handling in an MVVM context, but it should work for most cases that might occur in real-world App projects.

The declaration of the MVVMbasics Event Binding mechanism consists of two parts that are typically done directly in XAML code:

  • First, for all events that shall be redirected to a command their XAML event handler is specified as EventToCommand (in most cases, this will be exactly one event, but you might as well specify the same handler for as many events as you like).
  • Second, the command that shall be invoked on each of these events is specified by binding it to the attached property Event.Command.

In addition, the namespace MVVMbasics.Helpers (in which the attached property Event.Command is defined) needs to be declared within the View’s header. This is defined withing the MVVMbasicsWPF (for WPF applications), or MVVMbasicsRT (for WinRT projects, e.g. Universal Apps), or MVVMbasicsPS (for Windows Phone Silverlight Apps) assembly, respectively.

All this is shown in the following two examples:

  1. Binding a single event to a command:

    <views:BaseView
            xmlns:mvvm="clr-namespace:MVVMbasics.Helpers;assembly=MVVMbasicsWPF"
            ...other properties and namespace declarations follow here... >
    	<ListBox SelectionChanged="EventToCommand" mvvm:Event.Command="{Binding SelectionChangedCommand}">
    		... other properties and ListBox contents ...
    	</ListBox>
    </views:BaseView>
    
  2. Binding multiple events to the same command:

    <views:BaseView
            xmlns:mvvm="clr-namespace:MVVMbasics.Helpers;assembly=MVVMbasicsWPF"
            ...other properties and namespace declarations follow here... >
    	<CustomControl DoubleClick="EventToCommand" DoubleTapped="EventToCommand"
    		mvvm:Event.Command="{Binding ActivatedCommand}" />
    </views:BaseView>
    

This solution has two major drawbacks:

  • It allows binding only one custom command (in addition to the built-in Command Binding functionality of most controls) to an arbitrary number of control events. As in the above example, it is possible to bind both the DoubleClick and the DoubleTapped (and as many other events as are desired) to the ActivatedCommand. However, it would not be possible to bind each of these events to a separate command.
  • On the Windows Phone Silverlight (not Universal Apps!) platform, there exists a bug that prevents setting inherited event handlers in XAML code. As a workaround, we can declare the assign handlers in the View’s constructor:
    public MyPage()
    {
    	InitializeComponent();
    
    	MyListBox.SelectionChanged += EventToCommand;
    	// add the EventToCommand handler also to all other events that shall be redirected to a command
    }
    

    Unfortunately, this again includes code-behind coding, but limited to a few simple statements in the constructor (in comparison to declaring full event handlers that need to access the View’s Viewmodel, when using the conventional approach of handling control events). The command binding itself using Event.Command="{Binding CommandName}" can be done within XAML as on the other platforms.

As mentioned before, this is a workaround that cannot provide all the functionalities that would be desirable for an event-to-command binding mechanism, but it’s a start that should fit most applications. Let’s hope that a real platform-independent solution is introduced in future versions of .NET!