How to select TreeView item from code
Another option would be to use binding. If you have an object that you are using binding with to get the text of each TreeViewItem
(for example), you can create a style that also binds the IsSelected
property:
<TreeView> <TreeView.Resources> <Style TargetType="TreeViewItem"> <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" /> </Style> </TreeView.Resources></TreeView>
This assumes that the bound object has an IsSelected
property of type bool
. You can then select a TreeViewItem
by setting IsSelected
to true
for its corresponding object.
The same approach can be used with the IsExpanded
property to control when a TreeViewItem
is expanded or collapsed.
You can use the following TreeView
extension, which I find is a simpler solution:
public static class TreeViewExtension{ public static bool SetSelectedItem(this TreeView treeView, object item) { return SetSelected(treeView, item); } private static bool SetSelected(ItemsControl parent, object child) { if (parent == null || child == null) return false; TreeViewItem childNode = parent.ItemContainerGenerator .ContainerFromItem(child) as TreeViewItem; if (childNode != null) { childNode.Focus(); return childNode.IsSelected = true; } if (parent.Items.Count > 0) { foreach (object childItem in parent.Items) { ItemsControl childControl = parent .ItemContainerGenerator .ContainerFromItem(childItem) as ItemsControl; if (SetSelected(childControl, child)) return true; } } return false; }}
For more info, read this blog article; http://decompile.it/blog/2008/12/11/selecting-an-item-in-a-treeview-in-wpf/
After trying different sollutions I came to this site. Zhou Yong shows how to programatically expand all nodes of TreeView. There are two main ideas in his method:
- ContainerFromItem will return container only if item is direct child of the element. In TreeView that means that only first level child container will be returned and you have to call ContainerFromItem on child TreeViewItem to get container from next level
- For ContainerFromItem to work TreeViewItem visual children should be created and this happens only when TreeViewItem is expanded. That means that to select TreeViewItem all items preceding required item must be expanded. In practice that means that we will have to provide path to the item we want to select instead of just the item.
Here is the code I ended up with
public static void SelectItem(this ItemsControl parentContainer, List<object> path){ var head = path.First(); var tail = path.GetRange(1, path.Count - 1); var itemContainer = parentContainer.ItemContainerGenerator.ContainerFromItem(head) as TreeViewItem; if (itemContainer != null && itemContainer.Items.Count == 0) { itemContainer.IsSelected = true; var selectMethod = typeof(TreeViewItem).GetMethod("Select", BindingFlags.NonPublic | BindingFlags.Instance); selectMethod.Invoke(itemContainer, new object[] { true }); } else if (itemContainer != null) { itemContainer.IsExpanded = true; if (itemContainer.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated) { itemContainer.ItemContainerGenerator.StatusChanged += delegate { SelectItem(itemContainer, tail); }; } else { SelectItem(itemContainer, tail); } }}