Here is another early release of the MVVM Light Toolkit V3 (Alpha 2). I decided to release gradually and early as soon as a new part of this new version is ready, to allow advanced users to install, test and give feedback about the new features. If you haven’t seen it yet, the features available in V3 Alpha 1 are described in a previous article. There will be a few more alphas before I make a V3 release, which means more good things are a-coming 😉
Usual disclaimer: Alpha releases are not feature complete (meaning that APIs may change) and it is very possible that there are bugs in the code. Use with care and give feedback if something is not working, thanks!!
EventToCommand behavior
The new feature available in V3 Alpha2 is called EventToCommand and is a Blend behavior. These pieces of code are optimized for Expression Blend, but can also be added directly in XAML, as we will see in this article.
EventToCommand is used to bind an event to an ICommand directly in XAML.
Note: Even though Expression Blend facilitates the usage of EventToCommand, it is not a prerequisite. EventToCommand can be used even if Expression Blend is not installed on your system, or on your users’ system.
Credits, History
This behavior reuses much code from the Expression Blend sample behavior named InvokeDataCommand. I want to give props to the Expression team for creating and publishing these great samples. This would not have been possible without the work put into these samples. I want to especially thank Pete Blois and Jeff Kelly of the Expression team for their help.
I also want to thank Rishi, the creator of the nRoute toolkit, for the interesting discussions and a couple of ideas that I implemented in EventToCommand.
If you are already using InvokeDataCommand, the new EventToCommand behavior brings the following additional features:
If you are already using InvokeDataCommand, the new EventToCommand behavior brings the following additional features:
Source code, Binaries
The source code is available for download from my website. If you prefer, you can go to the Codeplex page where the source code has also been updated.
The binaries can be found here.
Features, Usage
EventToCommand is a behavior that can be added to any FrameworkElement. This can be a Rectangle, an Ellipse (in fact, any shape), an Image, any Control (Button, Slider, CheckBox, RadioButton, and many many others) etc. In short: If you can add an element to your UI, you can probably add EventToCommand to it.
For more information about ICommand (and their MVVM Light implementation, RelayCommand), read this article. You can bind any event to any command. Typically, you will use this to link an element’s event to a command defined in a ViewModel class. For more information about the ViewModel pattern in WPF and Silverlight, this page will help you.
In Expression Blend:
Adding an EventToCommand to any element in Expression Blend is super easy thanks to the visual support.
Right click on the References folder and select “Add Reference”.
- Add a reference to the MVVM Light DLLs. You need two: GalaSoft.MvvmLight.dll and GalaSoft.MvvmLight.Extras.dll. In addition, you need the System.Windows.Interactivity.dll which contains the base code for all behaviors.
You can download the DLLs needed here. - Open your project in Expression Blend, and build it to make sure that everything is working fine.
- Locate the element on which you want to add a command in the Objects and Timeline panel.
- Open the Assets panel and find the Behaviors category.
You can also find behaviors in the Asset library, which is the last button on the bottom of the toolbar.
- Drag the EventToCommand behavior on the element you selected before in the Objects and Timeline panel.
- With the EventToCommand selected, select the Properties panel.
- Select the event you want to handle
- In the Miscellaneous section, bind the EventToCommand to the ICommand you want to execute when the event is fired.
If you use the MVVM pattern, you probably want to use an ICommand (for example a RelayCommand) located in the ViewModel that is set as the DataContext for your window/page.
In WPF, you can also enter a value, for example ApplicationCommands.Save. In that case, you must set a CommandBinding.
- If you want to pass a parameter to the ICommand, you can set the CommandParameter property. You can data bind CommandParameter to something (for example the Text property of a TextBox, etc…). If you want to set a hard coded value ) for example “Hello world”, you need to set CommandParameterValue in the XAML editor (see the “Caveat” section below).
- Finally, if you want the attached element to be disabled depending on the ICommand.CanExecute method, set the MustToggleIsEnabledValue property to True. You can also use MustToggleIsEnabled to data bind this property to something else (for example a CheckBox’s IsChecked property) (see the “Caveat” section below).
- In Silverlight, this will only work on Controls. Use the VisualStateManager to modify the appearance of the disabled control.
- In WPF, any FrameworkElement can be disabled. Use the Triggers panel to modify the appearance of the FrameworkElement when it is disabled.
In XAML
Using the XAML editor, follow the steps to add an EventToCommand to an element.
- Add a reference to the MVVM Light DLLs. You need two: GalaSoft.MvvmLight.dll and GalaSoft.MvvmLight.Extras.dll. In addition, you need the System.Windows.Interactivity.dll which contains the base code for all behaviors.
You can download the DLLs needed here. - Add an xmlns for the following namespaces:
1.
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
2.
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras"
- Add the EventToCommand to the desired element (in this example, a Rectangle) with the following XAML code:
This presupposes that the DataContext of your page/window is set to a ViewModel containing the TestCommand command, as is usual in the MVVM pattern.
01.
<Rectangle Fill="White"
02.
Stroke="Black"
03.
Width="200"
04.
Height="100">
05.
<i:Interaction.Triggers>
06.
<i:EventTrigger EventName="MouseEnter">
07.
<cmd:EventToCommand Command="{Binding TestCommand,
08.
Mode=OneWay}"
09.
CommandParameter="{Binding Text,
10.
ElementName=MyTextBox,
11.
Mode=OneWay}"
12.
MustToggleIsEnabledValue="True" />
13.
</i:EventTrigger>
14.
</i:Interaction.Triggers>
15.
</Rectangle>
Listening to events on other elements
Because EventToCommand derives from System.Windows.Interactivity.TriggerAction<T>, it has a property named SourceName. With this property, you can attach EventToCommand to an element, but listen to events on another element. I didn’t explicitly forbid this in the code, but I would recommend against it. I think that it creates confusing code that can easily be broken. The best is probably to always listen to events on the attached element itself, and leave SourceName empty
Small caveat
Because of limitations in the Silverlight framework (specifically, the fact that data bindings can only be applied to a FrameworkElement), I had to resort to a small trick to make CommandParameter and MustToggleIsEnabled bindable. You will see in the code that there are four properties:
- CommandParameter:
- In Silverlight, used to data bind CommandParameter.
- In WPF, used either for data binding or for hard coded values.
CommandParameterValue:
In Silverlight and in WPF, used for hard coded values only.
MustToggleIsEnabled:
- In Silverlight, used to data bind MustToggleIsEnabled.
- In WPF, used either for data binding or for hard coded values.
MustToggleIsEnabledValue:
In Silverlight and in WPF, used for hard coded values only.
In short, if you don’t care about Silverlight compatibility for your XAML code, you can always use CommandParameter or MustToggleIsEnabled in WPF, either for data binding or for hard coded values. If you want to share your XAML between a Silverlight and a WPF application, then you should respect the rules above, or else you will get exceptions in Silverlight when the XAML is being parsed.
Demo application
The demo application shows multiple usages of the EventToCommand behavior. The application runs in Silverlight and in WPF. Feel free to download the code and play with it to learn how to use EventToCommand!
- Binding a Button’s Click event and a Rectangle’s MouseEnter event to a simple RelayCommand.
- Binding a Button’s Click event and a Rectangle’s MouseEnter event to a RelayCommand with a data bound parameter.
- Binding a Button’s Click event and a Rectangle’s MouseEnter event to a RelayCommand with a hard coded parameter.
- Binding a Button’s Click event and a Rectangle’s MouseEnter event to a RelayCommand and disabling them depending on the parameter’s value.
Note: In Silverlight, Rectangles cannot be disabled.
License
MVVM Light Toolkit is distributed under the MIT License. This license grants you the right to do pretty much anything you want with the code, but don’t come crying if you break something (the exact wording is found here). Some parts of the GalaSoft.MvvmLight.Extras DLL are licensed under the MS-PL license.
Laurent Bugnion (GalaSoft)
Subscribe | Twitter | Facebook | Flickr | LinkedIn