[WPF][MVVM] TreeView: Scroll To Selected Item

By | September 2, 2015

Advertisement from Google

Here is the MVVM way to bring selected TreeViewItem into a view.

First we need an attached behavior. We cannot use regular behavior because we will attach this property through Style.

public class BringSelectedItemIntoViewBehavior
{
	public static readonly DependencyProperty IsBringSelectedIntoViewProperty = DependencyProperty.RegisterAttached(
		"IsBringSelectedIntoView", typeof (bool), typeof (BringSelectedItemIntoViewBehavior), new PropertyMetadata(default(bool), PropertyChangedCallback));

	public static void SetIsBringSelectedIntoView(DependencyObject element, bool value)
	{
		element.SetValue(IsBringSelectedIntoViewProperty, value);
	}

	public static bool GetIsBringSelectedIntoView(DependencyObject element)
	{
		return (bool) element.GetValue(IsBringSelectedIntoViewProperty);
	}

	private static void PropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
	{
		var treeViewItem = dependencyObject as TreeViewItem;
		if (treeViewItem == null)
		{
			return;
		}

		if (!((bool) dependencyPropertyChangedEventArgs.OldValue) &&
			((bool) dependencyPropertyChangedEventArgs.NewValue))
		{
			treeViewItem.Unloaded += TreeViewItemOnUnloaded;
			treeViewItem.Selected += TreeViewItemOnSelected;
		}
	}

	private static void TreeViewItemOnUnloaded(object sender, RoutedEventArgs routedEventArgs)
	{
		var treeViewItem = sender as TreeViewItem;
		if (treeViewItem == null)
		{
			return;
		}

		treeViewItem.Unloaded -= TreeViewItemOnUnloaded;
		treeViewItem.Selected -= TreeViewItemOnSelected;
	}

	private static void TreeViewItemOnSelected(object sender, RoutedEventArgs routedEventArgs)
	{
		var treeViewItem = sender as TreeViewItem;
		treeViewItem?.BringIntoView();
	}
}

Advertisement from Google

And now we can attach this behavior through property in a ItemContainerStyle:

<TreeView>
	<TreeView.ItemContainerStyle>
		<Style TargetType="{x:Type TreeViewItem}">
			<Setter Property="local:BringSelectedItemIntoViewBehavior.IsBringSelectedIntoView" Value="True"/>
			<Setter Property="IsSelected"
					Value="{Binding IsSelected, Mode=TwoWay}" />
		</Style>
	</TreeView.ItemContainerStyle>
</TreeView>

Done! Just set IsSelected to true from code.

Here is full project (C# 6.0) on GitHub

Leave a Reply

Your email address will not be published. Required fields are marked *