WPF Treeview root node

Unfortunately the WPF native treeview or treeview items do not expose a property to determine which item is the root node in the treeview. I needed such a feature and thought to put it on my blog…

What is a treeview?
Well believe it or not a TreeView is just an Items Control nothing more. Yes, an ItemsControl that creates TreeViewItems as it’s Item Containers. The TreeViewItems are also ItemsControl so a recursive data structure is formed and the TreeViewItems generate there own child nodes.

Today I will not go into details of how the treeview and ItemsControl work… For more info on this visit Dr.Wpf Blog. I will discuss more how I implemented the root nodes for the treeview.

So an ItemsControl has a very special method that one can override to do some custom logic, “PrepareContainerForItemOverride“. The following is the signature of the method

protected override void PrepareContainerForItemOverride(
    DependencyObject element, object item)

Basically this method gets called whenever an item (in our case a TreeViewItem) is being created and decorated with a DataTemplate (if set). In this method we can set a property of the TreeViewItem to identify the item as a root node.Ok, lets start. First we need to sub class the Treeview control. Once we did that we need a way how to attach information to the TreeViewItems… HMMM.. what better could do this then Attached Properties. Once we have all this, we need to set the attached property to True for the root nodes and we are done🙂 …. something like this

public class MyTreeView : TreeView
    {

        public static bool GetIsRootNode(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsRootNodeProperty);
        }

        public static void SetIsRootNode(DependencyObject obj, bool value)
        {
            obj.SetValue(IsRootNodeProperty, value);
        }

        public static readonly DependencyProperty IsRootNodeProperty =
            DependencyProperty.RegisterAttached("IsRootNode", typeof(bool),
            typeof(MyTreeView), new UIPropertyMetadata(false));

        protected override void PrepareContainerForItemOverride(
            DependencyObject element, object item)
        {
            SetIsRootNode(element, true);
            base.PrepareContainerForItemOverride(element, item);
        }
    }

So the most important part is where we set the Attached property IsRootNode to true (Please also note that by default the Attached property is set to false). You would be wondering, But wouldn’t this make all TreeViewItems root nodes???!!??? And the answer is, NO. Because the Treeview only generate root nodes. all other nodes are generated by the TreeViewItems themselves (Remember that the TreeViewItems are ItemsControl as well :)).

Once we have the property IsRootNode set we can restyle the TreeView as we want by using a Control Template. something like this

<ControlTemplate TargetType="TreeViewItem">
    <StackPanel Margin="10,2,0,0">
        <WrapPanel Name="item">
            <ToggleButton Name="expander"
                          IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, 
                                              Path=IsExpanded}"
                          Content="+"/>
            <ContentPresenter x:Name="PART_Header"
                  ContentSource="Header" />
        </WrapPanel>
        <Border>
            <ItemsPresenter Name="children" Visibility="Collapsed" />
        </Border>
    </StackPanel>
    <ControlTemplate.Triggers>
        <Trigger Property="IsSelected" Value="True">
            <Setter TargetName="item" Property="Background"
                    Value="LightBlue"/>
        </Trigger>
        <Trigger Property="IsExpanded" Value="True">
            <Setter TargetName="children" Property="Visibility"
                    Value="Visible"/>
        </Trigger>
        <Trigger Property="HasItems" Value="False">
            <Setter TargetName="expander" Property="Visibility"
                    Value="Collapsed"/>
        </Trigger>
        <Trigger Property="local:MyTreeView.IsRootNode" Value="True">
            <Setter TargetName="item" Property="Background" Value="Silver"/>
            <Setter TargetName="item" Property="Height"  Value="50"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

The most important part of this ControlTemplate is the Trigger on the attached property local:MyTreeView.IsRootNode.Here we are making the RootNodes for the treeview look different from all other nodes…

Hope this post helps…. Please contact me if you need any help🙂

Download the full source code

6 thoughts on “WPF Treeview root node

  1. Hi, very useful information….very very thanks….
    i need another help…Is there any way to convert this Control Template xaml to c# code ?????

  2. Thank you Very Much, this has become my Best material in WPF Tree View Control topic. You made this very simple and understandable. Some good articles also helped me lot in completing my task which I was found during searching time of this article over internet. URL of those post are…
    http://www.c-sharpcorner.com/uploadfile/mahesh/treeview-in-wpf/
    http://www.codeproject.com/Articles/20645/WPF-TreeView-Selection
    and
    http://mindstick.com/Articles/2e32e73c-6298-4119-bd56-cf49a9b00a7f/?TreeView%20control%20in%20WPF

    Thank you very much everyone for your valuable post.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s