Thursday 10 September 2009

WPF TreeView Clear Selection

I needed to enhance an interface by swapping a listbox for a tree view. The data structures needed to be more complex to represent the tree structure but it was all very straight forward. A few minutes making a couple of HierarchicalDataTemplate to format the tree items and it was all working just as I wanted it.

Job done I thought and a great example of WPF's cool productivity gains etc.

There was just one little thing to complete. At one point the app needs to clear the selected item, so nothing remains selected. When using the ListBox this was a one liner:

listBox.SelectedIndex = -1;

TreeView does not have a SelectedIndex, but it does have a SelectedItem, which unfortunately is a read only property.

So this was not going to be easy and took a lot more time to solve than the rest of the conversion did.

There is a IsSelected property on each TreeViewItem in the tree. Find the selected object and set IsSelected to false and that clears the selection.

This being WPF a TreeView can contain objects of any class in its structure. No need to use TreeViewItems like in older frameworks.  So the following will not work as SelectedItem could return anything.

treeView.SelectedItem.IsSelected = false

The way the TreeView works is to generate TreeViewItems in the background that link to the actual data objects that you provide. So we need to get hold of each of the these using the TreeView's  ItemContainerGenerator and then set the IsSelected property to false. To make matters more complex the data is stored in a tree structure with each item acting as a tree in its own right. We have to walk the entire tree to find the selected item.

So here is the solution I came up with to enable me to clear the TreeView selection in a single line of code.

TomWrightsUtils.ClearTreeViewSelection(treeView);

Like all my favourite tree algorithms it uses recursion to do the job.

    class TomWrightsUtils
    {
        public static void ClearTreeViewSelection(TreeView tv)
        {
            if (tv != null)
                ClearTreeViewItemsControlSelection(tv.Items, tv.ItemContainerGenerator);
        }
        private static void ClearTreeViewItemsControlSelection(ItemCollection ic, ItemContainerGenerator icg)
        {
            if ((ic != null) && (icg != null))
                for (int i = 0; i < ic.Count; i++)
                {
                    TreeViewItem tvi = icg.ContainerFromIndex(i) as TreeViewItem;
                    if (tvi != null)
                    {
                        ClearTreeViewItemsControlSelection(tvi.Items, tvi.ItemContainerGenerator);
                        tvi.IsSelected = false;
                    }
                }
        }
    }

The First Post

The first post, its got to be the hardest. I have been getting around to writing it for years and now I have started it is not so hard after all.

The purpose of this blog....
To express myself, rants, opinions the usual stuff and probably more interesting for others is the tips, tricks, hacks and cool stuff I come across while developing.

What development stuff exactly
Its going to be C# and WPF for now as thats what I have been spending a lot of time on recently, but also C++, Ruby On Rails and Internet security as and when I spend some more time on them.

So best wind this post up now and write something that someone will find more useful.