MVVM how to move event handler from code behind to ViewModel
-
Tuesday, October 05, 2010 8:28 PM
First of all I'm fairly new to WPF and MVVM. For learning purposes I created a very simple MVVM test app similar to the one demonstrated here: http://windowsclient.net/learn/video.aspx?v=314683
I am trying to find out how to work with events in the MVVM pattern. To work with events in the xaml code behind is simple. But how to move the code to the ViewModel?
In the xaml I have:
<StackPanel Background="{Binding BackgroundBrush}">
<ItemsControl ItemsSource="{Binding AllEmployees}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBox Width="100" Text="{Binding FirstName}" />
<TextBox Width="100" Text="{Binding LastName}" TextChanged="eLastNameTextChanged" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Button Content="Check for invasion" Width="120" Command="{Binding InvasionCommand}" />
</StackPanel>You see that I want to fire an event on TextChanged. For that a method is generated in the xaml code behind:
// how to move this to the ViewModel???????
private void eLastNameTextChanged(object sender, TextChangedEventArgs e)
{
// MessageBox.Show("eLastNameTextChanged");
}But of course this is wrong in a pure MVVM approach. But how to get this code into the ViewModel?
Thanks!
All Replies
-
Tuesday, October 05, 2010 8:50 PMModerator
Your ViewModel will always see the last name changing, since it's bound. Just move your logic into the last name propertie's setter:
public string LastName { get { return this.lastName; } set { if (this.lastName != value) { this.lastName = value; this.RaisePropertyChanged("LastName"); // For INotifyPropertyChanged MessageBox.Show("eLastNameTextChanged"); } } }
Reed Copsey, Jr. - http://reedcopsey.com -
Tuesday, October 05, 2010 9:03 PM
@Tom
do not forget to set UpdateSourceTrigger=PropertyChanged of the Textbox so every time you type a char like 'a' the Property is raised in the viewmodel.
The Default value/behaviour for a TextBox is LostFocus.
-
Wednesday, October 06, 2010 9:44 AM
Thank you both (Also Lisa).
This was of course a stupid example from my side. I understand how to work with this specific example of a field change.
What I was after though was handling events in general in the MVVM approach. I took the wrong example. But suppose I would like to handle a MouseDown event. How should this be wired then?
Thanks.
-
Wednesday, October 06, 2010 2:47 PMModerator
Tom,
There are a few different approaches, all of which have trade offs.
My personal favorite approach is to use an Attached Property or a Behavior/Trigger (from Blend SDK) to allow an event to be converted into a bindable command. This lets you take an event handler, listen to it in the behavior, and wire it to a command on the VM.
The downside to this is that you tend to need to write a custom attached property or behavior for each type of event you want to handle. However, the upside is that this is written one time - and is reusable anywhere in your application. The attached property is also 100% view code, so it doesn't violate any of the MVVM goals.
For examples of how this works, see this blog post. Here is another post extending this to routed events.
Reed Copsey, Jr. - http://reedcopsey.com- Marked As Answer by Min ZhuMicrosoft Contingent Staff, Moderator Tuesday, October 12, 2010 1:46 AM
-
Wednesday, October 06, 2010 3:14 PM
Thanks, I will dive into it. Do you know a good code example somewhere on the web?
-
Wednesday, October 06, 2010 3:20 PMModerator
Thanks, I will dive into it. Do you know a good code example somewhere on the web?
I actually posted a sample on the Expression Code Gallery. It uses a Behavior to prevent the user from closing a Window unless a VM property allows it. It does this by trapping the Window Closing event and checking against a CanExecute on a bound property.
The code's very clean and simple - it might be a good place to get started.
Reed Copsey, Jr. - http://reedcopsey.com- Marked As Answer by Min ZhuMicrosoft Contingent Staff, Moderator Tuesday, October 12, 2010 1:46 AM
-
Wednesday, October 06, 2010 3:21 PM
Tom,
We have been successfully using this a lot in our code. Using this approach, you can bind any routed event to the View Model.
http://blog.functionalfun.net/2008/09/hooking-up-commands-to-events-in-wpf.htmlThanks,
Muhammad- Marked As Answer by Min ZhuMicrosoft Contingent Staff, Moderator Tuesday, October 12, 2010 1:46 AM
-
Wednesday, October 06, 2010 4:28 PMThanks, I'll check it out!
-
Wednesday, October 06, 2010 4:28 PMThis one too. Thanks.

