7

Selecting an item in a TreeView in WPF

Posted in .Net at December 11th, 2008 by Gerrod / 7 Comments »

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 &gt; 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!