Skip to content

Instantly share code, notes, and snippets.

@canton7
Created July 19, 2019 09:33
Show Gist options
  • Save canton7/f469e6e45a1094582c02549ca7a8d93e to your computer and use it in GitHub Desktop.
Save canton7/f469e6e45a1094582c02549ca7a8d93e to your computer and use it in GitHub Desktop.
TreeViewExtensions
/// <summary>
/// Extensions on TreeViews allowing users to bind to the SelectedItem property
/// </summary>
public static class TreeViewExtensions
{
private static readonly object initialBindingTarget = new object();
public static object GetSelectedItem(DependencyObject obj)
{
return obj.GetValue(SelectedItemProperty);
}
public static void SetSelectedItem(DependencyObject obj, object value)
{
obj.SetValue(SelectedItemProperty, value);
}
public static readonly DependencyProperty SelectedItemProperty =
DependencyProperty.RegisterAttached("SelectedItem", typeof(object), typeof(TreeViewExtensions), new FrameworkPropertyMetadata(initialBindingTarget, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, (d, e) =>
{
var treeView = d as TreeView;
if (treeView == null)
return;
// Trick to see if this is the first time we're set
if (e.OldValue == initialBindingTarget)
{
treeView.SelectedItemChanged += SelectedItemChanged;
treeView.ItemContainerGenerator.StatusChanged += (o2, e2) => ItemContainerGeneratorStatusChanged(treeView);
}
var container = ContainerFromItem(treeView.ItemContainerGenerator, e.NewValue);
if (container != null)
{
container.IsSelected = true;
}
}));
private static void ItemContainerGeneratorStatusChanged(TreeView treeView)
{
var containerGenerator = treeView.ItemContainerGenerator;
if (containerGenerator.Status != GeneratorStatus.ContainersGenerated)
return;
var container = ContainerFromItem(containerGenerator, GetSelectedItem(treeView));
if (container != null)
{
container.IsSelected = true;
}
}
private static TreeViewItem ContainerFromItem(ItemContainerGenerator containerGenerator, object item)
{
// From http://stackoverflow.com/a/24859863/1086121
var container = containerGenerator.ContainerFromItem(item) as TreeViewItem;
if (container != null)
{
return container;
}
foreach (object childItem in containerGenerator.Items)
{
var parent = containerGenerator.ContainerFromItem(childItem) as TreeViewItem;
if (parent == null)
continue;
container = parent.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;
if (container != null)
return container;
container = ContainerFromItem(parent.ItemContainerGenerator, item);
if (container != null)
return container;
}
return null;
}
private static void SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
var treeView = sender as TreeView;
if (sender == null)
return;
SetSelectedItem(treeView, e.NewValue);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment