Sometimes we need to handle the event in the view model. One simple approach is to introduce event properties in ViewModel and set it from the view as we saw in this example. Another approach is to convert event into command and use the command binding. In this method we are creating attach properties of ICommand type which calls the command whenever that event occurs.
First take a look at our program without any command binding. We are using MVVM and here is our ViewModel class.
{
private ObservableCollection<string> _states;
public MyViewMode()
{
_states = new ObservableCollection<string>();
_states.Add("Maryland");
_states.Add("Taxes");
_states.Add("Virginia");
_states.Add("Washington");
SelectionChanged = new MyCommand(HandleSelectionChangeEvent);
}
public ObservableCollection<string> States
{
get
{
return _states;
}
set
{
_states = value;
RaisePropertyChanged("States");
}
}
public ICommand SelectionChanged
{ get; set; }
public void HandleSelectionChangeEvent(string value)
{
MessageBox.Show(value);
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
We don’t have a separate Model class, because our data is list of string (in fact ObservableCollection of string) and we initilized it inside the ViewModel. We created one ICommand type property and create one method to handle that command. Here we are using MessageBox inside the ViewModel, which is just for simplicity purpose, in a proper ViewModel we shouldn’t have any user interface element inside ViewModel.
Our view class is very simple just create a ViewModel and assign it into DataContext.
{
public MainWindow()
{
InitializeComponent();
DataContext = new MyViewMode();
}
}
Our implementation of ICommand interface is very simple we are not doing any fancy stuff here and just give the minimal implementation of it. Here is our ICommnad interface implementation.
{
public Action<string> action
{ get; set; }
public MyCommand()
{
}
public MyCommand(Action<string> _action)
{
action = _action;
}
public bool CanExecute(object parameter)
{
if (action != null)
{
return true;
}
return false;
}
public void Execute(object parameter)
{
if (action != null)
{
action(parameter.ToString());
}
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}
If we run this program then it display the name of states in listbox (if we define listbox in XAML and set its items source property to States property of ViewModel). Now we are going to handle the Event and convert it into Command.
To do this we are going to create one class named ListBoxBehavior and define Attached dependency property in it. We already saw the attached properties here. We have to write as many attached dependency properties as many events we want to handle. In our example we are going to handle only one event.
{
public static readonly DependencyProperty SelectionChangedCommandProperty =
DependencyProperty.RegisterAttached("SelectionChangedCommand",
typeof(ICommand), typeof(ListBoxBehavior));
public static void SetSelectionChangedCommand(UIElement obj, ICommand value)
{
obj.SetValue(SelectionChangedCommandProperty, value);
}
public static ICommand GetSelectionChangedCommand(UIElement obj)
{
return (ICommand)obj.GetValue(SelectionChangedCommandProperty);
}
}
In next step we are going to add two fields in this class one for dependency property type and other for routed event.
{
private static DependencyProperty _property;
private static readonly RoutedEvent _selectionChangedEvent = ListBox.SelectionChangedEvent;
public static readonly DependencyProperty SelectionChangedCommandProperty =
DependencyProperty.RegisterAttached("SelectionChangedCommand",
typeof(ICommand), typeof(ListBoxBehavior));
public static void SetSelectionChangedCommand(UIElement obj, ICommand value)
{
obj.SetValue(SelectionChangedCommandProperty, value);
}
public static ICommand GetSelectionChangedCommand(UIElement obj)
{
return (ICommand)obj.GetValue(SelectionChangedCommandProperty);
}
}
Note that the event we want to handle is stored in our field, in our example it is SelectionChanged event define in the base class of ListBox. Then we are going to define the PropertyMetaData for Attached property. The main reason to define meta data is to define the callback method. Here is updated version of our program now.
{
private static DependencyProperty _property;
private static readonly RoutedEvent _selectionChangedEvent = ListBox.SelectionChangedEvent;
public static readonly DependencyProperty SelectionChangedCommandProperty =
DependencyProperty.RegisterAttached("SelectionChangedCommand",
typeof(ICommand), typeof(ListBoxBehavior),
new PropertyMetadata(new PropertyChangedCallback(SelectionChangedCallBack)));
public static void SetSelectionChangedCommand(UIElement obj, ICommand value)
{
obj.SetValue(SelectionChangedCommandProperty, value);
}
public static ICommand GetSelectionChangedCommand(UIElement obj)
{
return (ICommand)obj.GetValue(SelectionChangedCommandProperty);
}
static void SelectionChangedCallBack(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
}
}
This callback method perform the trick. This callback function add the event handler for our event which calls whenever that event occurs and that handler is going to call our command method. Here is our callback method.
{
UIElement element = obj as UIElement;
_property = args.Property;
if (element != null)
{
if (args.OldValue != null)
{
element.AddHandler(_selectionChangedEvent, new RoutedEventHandler(EventHandler));
}
if (args.NewValue != null)
{
element.AddHandler(_selectionChangedEvent, new RoutedEventHandler(EventHandler));
}
}
}
This callback method register one method name EventHandler. Inside our EventHandler method we are getting the command from the dependency property (which we set from the XAML) and execute the command. Here is a code of our EventHandler.
{
DependencyObject obj = sender as DependencyObject;
if (obj != null)
{
ICommand command = obj.GetValue(_property) as ICommand;
if (command != null)
{
if (command.CanExecute(e))
{
ListBox lb = e.OriginalSource as ListBox;
if (lb != null)
{
command.Execute(lb.SelectedItem);
}
}
}
}
}
Here is our XAML code, which is quite straight forward.
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfEventToCommand"
Title="Event To Command" Height="350" Width="525">
<Grid>
<ListBox Margin="5" ItemsSource="{Binding States}" HorizontalContentAlignment="Stretch"
local:ListBoxBehavior.SelectionChangedCommand="{Binding SelectionChanged}">
</ListBox>
</Grid>
</Window>
In XAML we are using the attach dependency property of ListBoxBehavior class and assign our ICommand property to it and perform command binding.
Here is our complete C# code.
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace WpfEventToCommand
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MyViewMode();
}
}
public class MyViewMode : INotifyPropertyChanged
{
private ObservableCollection<string> _states;
public MyViewMode()
{
_states = new ObservableCollection<string>();
_states.Add("Maryland");
_states.Add("Taxes");
_states.Add("Virginia");
_states.Add("Washington");
SelectionChanged = new MyCommand(HandleSelectionChangeEvent);
}
public ObservableCollection<string> States
{
get
{
return _states;
}
set
{
_states = value;
RaisePropertyChanged("States");
}
}
public ICommand SelectionChanged
{ get; set; }
public void HandleSelectionChangeEvent(string value)
{
MessageBox.Show(value);
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public class MyCommand : ICommand
{
public Action<string> action
{ get; set; }
public MyCommand()
{
}
public MyCommand(Action<string> _action)
{
action = _action;
}
public bool CanExecute(object parameter)
{
if (action != null)
{
return true;
}
return false;
}
public void Execute(object parameter)
{
if (action != null)
{
action(parameter.ToString());
}
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}
public class ListBoxBehavior
{
private static DependencyProperty _property;
private static readonly RoutedEvent _selectionChangedEvent = ListBox.SelectionChangedEvent;
public static readonly DependencyProperty SelectionChangedCommandProperty =
DependencyProperty.RegisterAttached("SelectionChangedCommand",
typeof(ICommand), typeof(ListBoxBehavior),
new PropertyMetadata(new PropertyChangedCallback(SelectionChangedCallBack)));
public static void SetSelectionChangedCommand(UIElement obj, ICommand value)
{
obj.SetValue(SelectionChangedCommandProperty, value);
}
public static ICommand GetSelectionChangedCommand(UIElement obj)
{
return (ICommand)obj.GetValue(SelectionChangedCommandProperty);
}
static void SelectionChangedCallBack(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
UIElement element = obj as UIElement;
_property = args.Property;
if (element != null)
{
if (args.OldValue != null)
{
element.AddHandler(_selectionChangedEvent, new RoutedEventHandler(EventHandler));
}
if (args.NewValue != null)
{
element.AddHandler(_selectionChangedEvent, new RoutedEventHandler(EventHandler));
}
}
}
public static void EventHandler(object sender, RoutedEventArgs e)
{
DependencyObject obj = sender as DependencyObject;
if (obj != null)
{
ICommand command = obj.GetValue(_property) as ICommand;
if (command != null)
{
if (command.CanExecute(e))
{
ListBox lb = e.OriginalSource as ListBox;
if (lb != null)
{
command.Execute(lb.SelectedItem);
}
}
}
}
}
}
}
Now whenever we change the selection in list box it will display a message box with the value of newly selected item. The only violation of MVVM in this example is using MessageBox inside the ViewModel, but that is just for illustration purpose, we can do other useful stuff inside that method.

[...] already saw one example how to convert Event into Command here. But if we want to consume more than one event, then we have to write lots of repetitive code. Take [...]
By: Convert Event into Command in MVVM Model Revisited « Zeeshan Amjad's WPF Blog on August 8, 2011
at 4:26 pm
Dear Zamjad,
I am just getting up to speed with WPF programming, and I have needed to address the problem you have solved here so clearly.
Thank you for your work.
One question: shouldn’t the SelectionChangedCallBack method call RemoveHandler, rather than AddHandler, when args.OldValue is not null?
By: Noel Macara on August 10, 2011
at 8:56 am
Hi Noel
Thanks to llike this. Yes you are right it should be RemoveHandler. Thanks for pointing out the mistake
By: zamjad on August 11, 2011
at 7:53 am
Hi Sir , Assalam O Aliakum, i m also the student of Dept of Computer Science and Software Engineering , right now working on .Net tools, very inspired by ur linked in profiles and your blog. I know u r extremely buzy but it would be nice of u if u can tell few great tools or art of computer science to master to become a prolific software engineer. I will really appreciate any tips from u. I m 2nd in overall semesters.
By: Ali on August 30, 2011
at 10:17 am
Thanks to like my blog. With this generic interest it would be very difficult to give any sugesstion. As far as i understand, good software engineer should know how to balance between science and engineering. In other words he/she should know how much theory knowledge is necessary as well as at the same time able to write a production level code that can handle an enterprise level problems, not a proof of concept lab programs only. He should have a good understanding of Algorithm, data structure as well as programming paradigms, such as object oriented programming, generic programming, functional programming, recursive programming, dynamic programming and have knowledge about modeling language (UML) and design patterns.
I know it is already a lot, so i can suggest one point only. That is read a lot, weather it is a book, online article, magzine, blogs, other’s code etc and try to understand it by making it yourself. I hope I am more clear now. Please feel free to contact me if you have any problem. I will try my best to solve your problem under my capacity.
Regards
Zeeshan Amjad
By: Zeeshan Amjad on September 1, 2011
at 12:15 am
I m extremely thankful to u for tips and knowledge u share with me. Now a days i m studying computer graphics i have keen interest in mobile programming can u tell me which one is better android or iphone , well i know both are in demand to a great deal but just for a startup in 3rd semester what would u recommend.
i want to design my Computer Graphics project in mobile platform what will u recommend!
i m sorry for disturbing u again!
By: Ali on September 2, 2011
at 12:42 am
Both Andriod and iPhone development are very interesting. I got a chance to work on both and explore both while making some POC (Proof of Concept). To develop iPhone application, there are two major hurdles, one is software and other is hardware. You have to have Mac computer and have to learn Objective-C language. Although it is not very difficult, but little bit different thinking style. However for Andriod you can do programming on Windows based compuer using Java and don’t have to learn a new language (if you already know Java).
Even if learning a new language is not a big problem, then still Mac book is an important factor to make the decision.
By: Zeeshan Amjad on September 2, 2011
at 11:49 am
Great article. Wouldn’t I have to modify this a bit more to support events raised by the controls hosted in user controls?
By: Prakash on November 15, 2011
at 12:15 am
Thanks to like it. Maybe, i haven’t done this type of work on user control yet. Once i will do this work with user control, i will post my finding here.
Regards
Zeeshan Amjad
By: Zeeshan Amjad on November 21, 2011
at 5:24 pm
Hi Zeeshan!
Thank you so much for this Demo. It works perfectly in my WPF app. Now I am trying to convert it to Silverlight(5) BUT, Silverlight doesn’t have ListBox.SelectionChangedEvent(Routed Event). Could you please let us know how to rewrite the code for Silverlight?
Thank you,
-Avantika
By: Avantika on February 1, 2012
at 5:36 pm
HI Avantika.
But what i saw from the MSDN it is supported since Silverlight 3. Take a look at the following page.
http://msdn.microsoft.com/en-us/library/system.windows.controls.primitives.selector.selectionchanged(v=vs.95).aspx
Can you please explain it a bit what you are trying to do?
Regards
Zeeshan Amjad
By: Zeeshan Amjad on February 20, 2012
at 11:17 am