Selecting an item in a TreeView in WPF
I have to admit that I much prefer WPF over Windows Forms (but prefer ASP.Net to either). However, the programming model is still a bit immature (in my opinion), and sometimes things that you wish were simple just aren’t. Case and point: trying to programmatically select an item in a TreeView control; it just ain’t easy!
Anyway, after scrubbing the web and finding a few solutions that really didn’t appeal (e.g. using reflection; surely it’s not that hard!) I came up with this extension method which does the trick quite nicely.
/// <summary>
/// Walks the tree items to find the node corresponding with
/// the given item, then sets it to be selected.
/// </summary>
/// <param name="treeView">The tree view to set the selected
/// item on</param>
/// <param name="item">The item to be selected</param>
/// <returns><c>true</c> if the item was found and set to be
/// selected</returns>
static public bool SetSelectedItem(
this TreeView treeView, object item) {
return SetSelected(treeView, item);
}
static private 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;
}
(Forgive formatting; the code window is only so-wide.)
The trick, you see, is to use the ItemContainerGenerator on the ItemsControl – which TreeView and TreeViewNode both inherit from – to try to find the container for the item you are selecting. This will only work for the immediate children of the control that you’re calling it on – so asking your root node for the container for an item which is three nodes deep is fruitless; hence, you have to walk down the tree asking each branch node if it contains the item.
It’s possibly not the fastest executing code in the world – walking a tree rarely is – but you could speed things up if you knew where the parent node was; then you could just call the recursive method directly.
Enjoy!
April 22nd, 2009 at 3:38 am #Robert Bouillon
Note that you can only walk down the visual tree if it has been built (i.e. all nodes are expanded). Once you set IsExpanded to true, you have to let the Generator render the visual elements and then try again once it has completed.
You can do this by re-calling SetSelectedItem on ItemContainerGenerator.StatusChanged where ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated.
I don’t understand how something as fundamental as a set accessor on SelectedItem made it through a design review.
July 1st, 2009 at 6:31 am #Subalakshmi Vijayarajan
Hi,
Thanks for your code snippet. It really helped me a lot. Thanks a lot
Best Regards,
Subalakshmi Vijayarajan.
September 15th, 2009 at 10:06 pm #Get a TreeViewItem’s Parent item - Quickduck
[...] to Gerrod’s post on selecting an item in a treeview, I found myself scratching my head on how to find a treeviewitem’s parent item. Here I was [...]
October 7th, 2009 at 6:09 am #vishnu vardhan
Thanks for your code snippet. It really helped me a lot. Thanks a lot
October 7th, 2009 at 6:11 am #vishnu vardhan
I want to how many child are available in one root node in treeview in wpf application? please give the sample code
October 14th, 2009 at 5:32 am #Sean McElroy
I wasted about three hours on this until I finally came across your blog. You’re a life saver.
January 20th, 2010 at 5:01 pm #Karthick
I had been looking for this and finally your blog helped after 5 hours of search. Thanks. This is wonderful work.