This is the second part of the MVVM Light Toollkit Soup To Nuts (part 1 is here) within the Windows Phone From Scratch Mini-tutorial series. Today we look at an introduction to behaviors as a tool for migrating event handling from code-behind to the View-Model.
Behaviors were originally introduced in Blend to empower designers, but they turn out to be enormously helpful to C# programmers as well. For example, it is a design goal to move as much of the (testable) logic of the program out of code-behind (where testing is more difficult) and into the View-Model. But what to do about events, such as the click event on a button?
What We’ll Build
To illustrate this, we’ll return to the example we began in part 1, and extend it by adding a button to MainPage that will cause the application to navigate to page 2. We’ll do this in two steps:
- First we’ll substitute a behavior for the event handler
- Second we’ll use messages (in part 3) to tell the page to navigate to the new page
To get started, re-open MvvmLightNavigationBehaviorAndMessages in Expression Blend (if you don’t have the project, you can download the source code here.)
Make the following changes to MainPage.xaml
- Remove the text box
- Add a row towards the top of the content grid
- Place a button, centered, into that row with the content Page 2, named Page2Button.
Click on Assets and then click on Behaviors. Drag EventToCommand down to the Objects and Timeline window and onto Page2Button. When you release the mouse, you’ll find [EventCommand] as a child of the button. Go to the properties window and name it Page2ButtonClicked.
Leave the EventName as click. We’ll want to bind to a command in the code behind, so save all the files and switch over to the same project in Visual Studio.
Creating the Bindable Behavior Property
In the View-Model for MainPage (MainViewModel.cs, add a property for the command (of type RelayCommand):
public RelayCommand Page2Command { get; private set; }
You’ll need to add a using statement for RelayCommand
using GalaSoft.MvvmLight.Command;
Next we’ll initialize the value of the property in the constructor for MainViewModel,
public MainViewModel() { Page2Command = new RelayCommand( () => GoToPage2() );
This sets the property (Page2Command) to call a method named GoToPage2. You can stub that out for now as follows:
private object GoToPage2() { System.Windows.MessageBox.Show( "Navigate to Page 2!" ); return null; }
Save and build the application and then return to Expression Blend. In the properties window for the Page2ButtonClicked command find the Command property (under Miscellaneous) and click on the property peg and choose Bind. The CreateDataBinding dialog opens. Select Page2Command and click OK.
Run the project and when you click on the Page2 button a dialog box opens with the text you specified(!)
What Have You Done?
What you’ve done is to bind a behavior to a property in the code behind. The property is initialized not with a value but with a method that is invoked when the behavior is triggered.
You can see the missing bit by opening the Xaml for the Button, in MainPage.xaml,
<Button x:Name="Page2Button" Content="Page 2" Margin="0" Grid.Row="1" d:LayoutOverrides="Width, Height" HorizontalAlignment="Center" VerticalAlignment="Center"> <Custom:Interaction.Triggers> <Custom:EventTrigger EventName="Click"> <GalaSoft_MvvmLight_Command:EventToCommand x:Name="Page2ButtonClicked" Command="{Binding Page2Command, Mode=OneWay}" /> </Custom:EventTrigger> </Custom:Interaction.Triggers> </Button>
The very good news is that the logic for handling the button click is now in the view-model rather than in the code behind.
In the next part of this series, we’ll look at how the view-model can send a message back to the view to take advantage of the view’s access to the navigation mechanism.
I see your website needs some fresh content. Writing manually takes a lot of time, but there
is tool for this time consuming task, search for; unlimited content Wrastain’s tools
I see you don’t monetize your website, don’t waste your traffic,
you can earn extra cash every month because you’ve got high quality content.
If you want to know how to make extra bucks, search for:
best adsense alternative Wrastain’s tools
Based on some of the recent comments I tried this out using the Button Command property.
First remove the EventToCommand behavior (assuming you’ve gone through all the steps above).
Select Page2Button. Under Miscellaneous, select the “peg” next to Command, select DataBinding and then select the Page2Command as before.
Works the same. Is this the recommend way of messaging with 7.1?
After doing everything up to GoToPage2(), when I save & Build and go back to Blend, I can’t touch the command property under miscellaneous
Make sure you click the little “peg” NEXT to the command property box
It’s way too much code when using MVVM Light comparing to using Prism. Command is at most one line of code with Prism. The “Light” means the template is light, and makes the code heavier.
Actually that does seem to me like a valid question. The Command property is supported on Button both in Silverlight 4 and Windows Phone 7.1.
http://msdn.microsoft.com/en-us/library/system.windows.controls.primitives.buttonbase.command(v=VS.95).aspx
But command cannot distinguish click and mouseover
Now I got it: It’s because in Silverlight there is no Button.Command property. It’s only available in WPF.
Chris, if I’m understanding you correctly, you’re saying that if one were using WPF, all they’d have to do is something like this:
am I correct?
Chris, et. al, I’ve got another question concerning the Command property. I’ve checked and found that with the release of Silverlight 4, it supports the Command property on the ButtonBase class (from Tim Heuer’s blog). So then, I’m kind of confused as to what the need is to go through connecting a command using behaviors. Why not just use the Command property of the button class?
I don’t see why we need the EventToCommand behavior here. Why not just simply bind the Button.Command property to Page2Command? This would also ensure that the button gets disabled when the command’s CanExecuteChanged method returns false.
I see that this is only an example, but it might be better to use an event for which there is no corresponding Command property (like ComboBox. SelectionChanged).
If you are having trouble seeing the behaviours, double check you have installed all the toolkit bits correctly – there is a link to it in part 1.
Great job Jesse, Great series so far 🙂
ohh.. i need to install lvvmlight to see that i think.. I just tried opening the project
I don’t see a ‘eventtocommand’ behaviour in my blend 4.. everyone else sees this?
great series of post. keep it up!