MVVM – Binding TreeView Item Changed to ICommand

Download Sample Project here: http://www.box.com/s/0e8rokffhp9p0pshb6b6

After browsing the web for more tha an hour there were quite some post which helped me to get a clue on how to bind a Tree View item selected.
All these posts gave me call back, on which I had to fire an event again, and add a subscription to it.

I wanted that call back subscription to be an ICommand, so that it is in sync with MVVM model.
But to bring the Call back into the View model had to go an extra mile.

I had to synchronize two dependency property.

1.  A dependency property to bind to  TreeView Item Selected .
2.  A dependency property to bind an ICommand, to  TreeView Item Selected Changed.

Dependency property to bind the TreeView Item Selected:

You need a dependency property which would hold the Tree View Item Selected value.
This property should be always updated with the New value, so that you would get an call back on SelectedItemChanged when a new item in the tree is selected.

public static readonly DependencyProperty SelectedItemProperty =
                       DependencyProperty.RegisterAttached("SelectedItem",
                                 typeof(object),
                                 typeof(TreeViewHelper),
                                 new UIPropertyMetadata(null, SelectedItemChanged));

Dependency property to bind an ICommand, when an TreeView Item Selected is changed:

You need a second dependency property which you could bind to an ICommand and execute when ever a new item in the treeview is selected.

public static readonly DependencyProperty SelectedItemChangedProperty =
                  DependencyProperty.RegisterAttached("SelectedItemChanged",
                                     typeof(ICommand),
                                     typeof(TreeViewHelper));

Code to fire the ICommand on SelectedItemProperty call back events

private static void SelectedItemChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
    if (!(obj is TreeView) || e.NewValue == null)
        return;

    var view = obj as TreeView;
    view.SelectedItemChanged += (sender, e2) => SetSelectedItem(view, e2.NewValue);

    var command = (ICommand) (view as DependencyObject).GetValue(SelectedItemChangedProperty);
    if (command != null)
    {
        if (command.CanExecute(null))
            command.Execute(new DependencyPropertyEventArgs(e));
    }
}

Here is the xaml code to bind these two dependency properties

<UserControl x:Class="TreeViewItemChangedMvvm.View.MyTreeViewControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:ViewModelUtils="clr-namespace:TreeViewItemChangedMvvm.ViewModelUtils" mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <TreeView ItemsSource="{Binding ItemsSource}"  
                  ViewModelUtils:TreeViewHelper.SelectedItem="{Binding CurrSelItem}"  
                  ViewModelUtils:TreeViewHelper.SelectedItemChanged="{Binding MySelItemChgCmd}" />
    </Grid>
</UserControl>

Thanks: http://stackoverflow.com/questions/1000040/selecteditem-in-a-wpf-treeview
Sample Project: http://www.box.com/s/0e8rokffhp9p0pshb6b6