Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Settings a TreeViewItem as not selectable

0.00/5 (No votes)
25 Jan 2013 1  
Settings a TreeViewItem as not selectable.

Introduction

I had a need to set some items in a TreeView as not selectable as they were top items of different types. Since the items were not of type TreeViewItem I had some limitations on how to do it.

Using the code

Since I like MVVM, this will be done using behaviors. We need to take over the items before they are presented to the user. Behaviors add to the control some sort of "behavior" and by that we are able to control how it responds to actions in our application.

We need to take over the loaded event as in this point the treeview finished loading and the items are already in the Items list of the treeview. In the loaded event we will go over all items in the list and find the ones we are looking for. The trick in having the items not selectable is simple: not giving them focus.

So first let's run over the items:

// Here we are setting the "ContainerViewModel" not focusable so we cannot select it.
private void TreeViewLoaded(object sender, RoutedEventArgs routedEventArgs)
{
    foreach (var item in AssociatedObject.Items)
    {
        if (item is ContainerViewModel)
        {
            SetNotFocusable(AssociatedObject, item);
        }
    }
}

The items in the list are of the type I've bound them to (different view models) so I can't really set focusable to false. I need a helper method that will do it for me. The helper method will need to run over the TreeViewItems in the list and find a requested item, and set its focusable property to false.

I got from the web a general method that gets a parent class for items named ItemsControl.

The first thing the method does is try and get the requested item from the ItemsControl children. As it can only get level 1 items, the method is recursive.

static private bool SetNotFocusable(ItemsControl parent, object child)
{
    if (parent == null || child == null)
        return false;

    TreeViewItem childNode = parent.ItemContainerGenerator
        .ContainerFromItem(child) as TreeViewItem;

    if (childNode != null)
    {
   
        return childNode.Focusable = false;
    }
}

We are using above the method ContainerFromItem in order to get the TreeViewItem itself from the object we need, which the TreeViewItem wraps. Once found, we set its Focusable property to false.

If not found then we need to go over the children, and if one of them is a container itself then go inside.

if (parent.Items.Count > 0)
{
    foreach (object childItem in parent.Items)
    {
        ItemsControl childControl = parent
            .ItemContainerGenerator
            .ContainerFromItem(childItem)
            as ItemsControl;

        if (SetNotFocusable(childControl, child))
        {
            return true;
        }
    }
}

If trying to find the object fails then return false.

Here is the complete method:

static private bool SetNotFocusable(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.Focusable = false;
    }

    if (parent.Items.Count > 0)
    {
        foreach (object childItem in parent.Items)
        {
            ItemsControl childControl = parent
                .ItemContainerGenerator
                .ContainerFromItem(childItem)
                as ItemsControl;

            if (SetNotFocusable(childControl, child))
            {
                return true;
            }
        }
    }

    return false;
}

Hope this will help you as it helped me.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here