Craig Shearer
Craig Shearer

Reputation: 14521

Can I control which nodes are selectable in a WPF TreeView?

I have a two-level hierarchy displayed in a WPF TreeView, but I only want the child nodes to be selectable - basically the top level nodes are for categorisation but shouldn't be selectable by themselves.

Can I achieve this?

Thanks...

Upvotes: 7

Views: 4507

Answers (4)

Ravid Goldenberg
Ravid Goldenberg

Reputation: 2299

You can make only the child nodes selectable by using a trigger in a style, assuming all child nodes have no child nodes, like so:

<TreeView Name="MyTreeView>
    <TreeView.ItemContainerStyle>
         <Style TargetType="{x:Type TreeViewItem}">
             <Style.Triggers>
                 <Trigger Property="HasItems" Value="true">
                     <Setter Property="Focusable" Value="False" />
                 </Trigger>
             </Style.Triggers>
          </Style>
     </TreeView.ItemContainerStyle>
</TreeView>

Setting Focusable to false on a father TreeViewItems also prevents them from being selected.

Upvotes: 1

Paul
Paul

Reputation: 83

Define styles for each type of items, like Bijington wrote. for non-selectable nodes set the Focusable-Property of the container (TreeViewItem for TreeViews) to false.

Upvotes: 5

Rob Fonseca-Ensor
Rob Fonseca-Ensor

Reputation: 15621

I've written at attached property that will unselect a treeviewitem as soon as it's selected:

public class TreeViewItemHelper
{
    public static bool GetIsSelectable(TreeViewItem obj)
    {
        return (bool)obj.GetValue(IsSelectableProperty);
    }

    public static void SetIsSelectable(TreeViewItem obj, bool value)
    {
        obj.SetValue(IsSelectableProperty, value);
    }

    public static readonly DependencyProperty IsSelectableProperty =
        DependencyProperty.RegisterAttached("IsSelectable", typeof(bool), typeof(TreeViewItemHelper), new UIPropertyMetadata(true, IsSelectablePropertyChangedCallback));

    private static void IsSelectablePropertyChangedCallback(DependencyObject o, DependencyPropertyChangedEventArgs args)
    {
        TreeViewItem i = (TreeViewItem) o;
        i.Selected -= OnSelected;
        if(!GetIsSelectable(i))
        {
            i.Selected += OnSelected;
        }
    }

    private static void OnSelected(object sender, RoutedEventArgs args)
    {
        if(sender==args.Source)
        {
            TreeViewItem i = (TreeViewItem)sender;
            i.IsSelected = false;
        }
    }
}

Unfortunately you still lose the old selection when you click on an unselectable item :(

Upvotes: 0

Bijington
Bijington

Reputation: 3751

To do so you would need to override the style for treeview. Ideally you will have two types of treeview items one for your top-level nodes (im assuming folders) and another simply for the children, then you should be able to define how each item type in the tree behaves. So create a style for each item type, then for the folder node simply change the trigger for is selected to do nothing.

Upvotes: 2

Related Questions