C# – Data binding to SelectedItem in a WPF Treeview


How can I retrieve the item that is selected in a WPF-treeview? I want to do this in XAML, because I want to bind it.

You might think that it is SelectedItem but apparently that does not exist is readonly and therefore unusable.

This is what I want to do:

<TreeView ItemsSource="{Binding Path=Model.Clusters}" 
            ItemTemplate="{StaticResource ClusterTemplate}"
            SelectedItem="{Binding Path=Model.SelectedCluster}" />

I want to bind the SelectedItem to a property on my Model.

But this gives me the error:

'SelectedItem' property is read-only and cannot be set from markup.

Ok, this is the way that I solved this:

          ItemsSource="{Binding Path=Model.Clusters}" 
          ItemTemplate="{StaticResource HoofdCLusterTemplate}"
          SelectedItemChanged="TreeView_OnSelectedItemChanged" />

and in the codebehindfile of my xaml:

private void TreeView_OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    Model.SelectedCluster = (Cluster)e.NewValue;

Best Solution

I realise this has already had an answer accepted, but I put this together to solve the problem. It uses a similar idea to Delta's solution, but without the need to subclass the TreeView:

public class BindableSelectedItemBehavior : Behavior<TreeView>
    #region SelectedItem Property

    public object SelectedItem
        get { return (object)GetValue(SelectedItemProperty); }
        set { SetValue(SelectedItemProperty, value); }

    public static readonly DependencyProperty SelectedItemProperty =
        DependencyProperty.Register("SelectedItem", typeof(object), typeof(BindableSelectedItemBehavior), new UIPropertyMetadata(null, OnSelectedItemChanged));

    private static void OnSelectedItemChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        var item = e.NewValue as TreeViewItem;
        if (item != null)
            item.SetValue(TreeViewItem.IsSelectedProperty, true);


    protected override void OnAttached()

        this.AssociatedObject.SelectedItemChanged += OnTreeViewSelectedItemChanged;

    protected override void OnDetaching()

        if (this.AssociatedObject != null)
            this.AssociatedObject.SelectedItemChanged -= OnTreeViewSelectedItemChanged;

    private void OnTreeViewSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        this.SelectedItem = e.NewValue;

You can then use this in your XAML as:

        <behaviours:BindableSelectedItemBehavior SelectedItem="{Binding SelectedItem, Mode=TwoWay}" />

Hopefully it will help someone!

Related Question