This post is about flexible styling for databound TreeViews in WPF. We will see how nested trees of any depth and structure can be bound easily with the HierarchicalDataTemplate.
In the next posts I will demonstrate use of the Composite Pattern to describe the hierarchical data and LINQ to XML to read the data from an XML file. Finally, I will put all the pieces together in an application that displays a trivial organization chart.
We will start with a set of classes that all have Composite as their base class. Composite might be defined like so:
class Composite
{
public string Name { get; set; }
public List<Composite> Children { get; set; }
}
Here is method that builds some sample data:
private List<Composite> GetData()
{
List<Composite> list = new List<Composite>()
{
new Composite { Name = "1", Children = new List<Composite>()
{
new Composite { Name = "1.1", Children = new List<Composite>()
{
new Composite { Name = "1.1.1" },
new Composite { Name = "1.1.2" },
new Composite { Name = "1.1.3" }
}
new Composite { Name = "2.1", Children = new List<Composite>()
{
new Composite { Name = "2.1.1" },
new Composite { Name = "2.1.2" },
new Composite { Name = "2.1.3" }
}
}
}
},
new Composite { Name = "3", Children = null }
};
return list;
}
We would like to bind this data to a TreeView named treeView like so:
treeView.ItemsSource = GetData();
Here is a first attempt at the XAML for treeView.
<TreeView Name="treeView">
<TreeView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}" />
</DataTemplate>
</TreeView.ItemTemplate>
</TreeView>
But this results in the display of the top level nodes only – like a ListBox.
The key is to introduce the HierarchicalDataTemplate like so:
<TreeView Name="treeView">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=Children}">
<TextBlock Text="{Binding Path=Name}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
This is the result:
So, the HierarchicalDataTemplate is used to style a current item and to generate items for those in its ItemsSource.
What happens if the second level nodes have a different type with different properties and we would like to present each type differently?
For instance, let’s define:
private static List<Composite> GetData()
{
List<Composite> list = new List<Composite>()
{
new Department { Name = "Division 1", Children = new List<Composite>()
{
new Department { Name = "Finance", Budget = 10, Children = new List<Composite>()
{
new Employee { Name = "Tom", Role="Accountant" },
new Employee { Name = "Sarah", Role="Accountant" },
new Employee { Name = "Harry", Role="Secretary" }
}
},
new Department { Name = "Sales", Children = new List<Composite>()
{
new Employee { Name = "Alice", Role="", Salary=11 },
new Employee { Name = "Mary", Role="", Salary=11 },
new Employee { Name = "Harry", Role="", Salary=11 }
}
}
}
},
new Composite { Name = "Division 2", Children = null }
The result, below is disappointing, but not surprising. All nodes look the same, because we are still using the same template for items of all types.

As you know, different DataTemplates can be applied automatically according to type by setting the DataType property.
We use this in the improved version of the XAML below. Here, there is a HierarchicalTemplate for each type.
<Window.Resources>
<HierarchicalDataTemplate DataType="{x:Type org:Department}"
ItemsSource="{Binding Path=Children}">
<Border BorderBrush="Green"
BorderThickness="1">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Department: " />
<TextBlock Text="{Binding Path=Name}" />
</StackPanel>
</Border>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type org:Manager}"
ItemsSource="{Binding Path=Children}">
<Border BorderBrush="Blue"
BorderThickness="1">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Manager: "></TextBlock>
<TextBlock Text="{Binding Path=Name}" />
<StackPanel Orientation="Horizontal">
<TextBlock Text=" Salary (" />
<TextBlock Text="{Binding Path=Salary}" />
<TextBlock Text=")" />
</StackPanel>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=EmployeeCount}" />
<TextBlock Text=" employees" />
</StackPanel>
</StackPanel>
</Border>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type org:Employee}"
ItemsSource="{Binding Path=Children}">
<Border BorderBrush="Red"
BorderThickness="1">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Employee: " />
<TextBlock Text="{Binding Path=Name}" />
<TextBlock Text=" Salary (" />
<TextBlock Text="{Binding Path=Salary}" />
<TextBlock Text=")" />
</StackPanel>
</Border>
</HierarchicalDataTemplate>
</Window.Resources>
All templates are in the Windows.Resources collection and the TreeView markup now looks like this:
<TreeView Name="treeView"/>
And this is the result:
Summary
In this post I demonstrated how to use the HierarchicalDataTemplate to bind data to a TreeView.
Using HierarchicalDataTemplate there is no need to hard code the structure of the tree in the markup. The structure of the tree is determined by the structure data that we bind to it.
My next post is about the representation of the business objects and the databinding.