#1,217 – Using Multiple HierarchicalDataTemplates in a TreeView

I showed last time how to use a HierarchicalDataTemplate as the ItemTemplate for a TreeView. This allowed us to specify the look and feel of each node in the tree and also dictated how the main data item would be traversed to generate the tree.

If you have some hierarchical data in which the items are not all of the same type, you can specify more than one HierarchicalDataTemplate for the TreeView, based on the underlying type of each node.

Let’s assume that we have both a Breed and a Dog class. Breed objects contain information about a breed and in turn have a Dogs property that is a list of individual dogs of that breed.

In the example below, we have a TreeView whose ItemsSource is bound to a list of breeds. We then include a template to use for each Breed item and a different template to use for each Dog item in the tree. We also indicate that the tree should be expanded by looking at the Dogs property in each breed instance.

        <TreeView Grid.Row="0" Margin="5" ItemsSource="{Binding Breeds}">
            <TreeView.Resources>
                <HierarchicalDataTemplate DataType="{x:Type loc:Breed}" ItemsSource="{Binding Dogs}">
                    <StackPanel Orientation="Horizontal" Margin="0,5,0,0">
                        <TextBlock Text="Breed:"/>
                        <TextBlock Margin="5,0,0,0" FontWeight="Bold" Text="{Binding Name}"/>
                    </StackPanel>
                </HierarchicalDataTemplate>

                <HierarchicalDataTemplate DataType="{x:Type loc:Dog}">
                    <StackPanel Orientation="Horizontal" Margin="0,2,0,0">
                        <TextBlock Text="{Binding}"/>
                    </StackPanel>
                </HierarchicalDataTemplate>
            </TreeView.Resources>
        </TreeView>

Note that we specify a DataType for each HierarchicalDataTemplate. As the tree is constructed, the appropriate template will be used, based on whether a node is a breed or a dog.

Below, we can see how this will look at runtime. Breed nodes show the breed’s name. Dog nodes show the dog’s name and age. We just have a TextBlock bound to the Dog instance as a whole, which causes the dog’s ToString method to get invoked. In our case, we’ve overridden ToString to display the dog’s name and age.

About Sean
Software developer in the Twin Cities area, passionate about software development and sailing.

5 Responses to #1,217 – Using Multiple HierarchicalDataTemplates in a TreeView

  1. Pingback: Dew Drop - September 18, 2017 (#2563) - Morning Dew

  2. Hi Sean,
    Thanks for that – do you know if there is any way of specifying to use a different template based upon property values within a single type (eg if you wanted “beagle => template X, Dalmation => template Y”)? Or, does it only work at type level?

    • Sean says:

      Hi Paul,

      I think that the easiest way would be to have a single hierarchical data template with multiple ContentPresenters, each of which lights up (Visibility) based on whatever criteria you want. (Create a converter if necessary). Then you could have multiple data templates wired up. Even better, actually, would be to have a ContentPresenter with a ContentTemplateSelector that picks the proper template.

      • Hi Sean, that’s great, thank you so much for the quick response. I’d found DataTemplates and DataTemplateSelectors, and used them successfully elsewhere in the project (first time on WPF), but hadn’t encountered ContentTemplateSelectors.

  3. Yvonnila says:

    Hi Sean,
    Thank you for your helpful post.
    I have a similar TreeView in my application. Where I use HierarchicalDataTemplate for each level.

    I want to change the style of the expanders. However, I don’t get it what exactly I need to edit. I know that I need to override the ControlTemplate of the TreeViewItems (is that correct?), but I don’t know where I need to apply it. I’d appreciate it a lot, if you could give me a hint about it.

Leave a comment