How to: Bind a TreeView to Data That Has an Indeterminable Depth

There might be times when you want to bind a TreeView to a data source whose depth is not known. This can occur when the data is recursive in nature, such as a file system, where folders can contain folders, or a company's organizational structure, where employees have other employees as direct reports.

The data source must have a hierarchical object model. For example, an Employee class might contain a collection of Employee objects that are the direct reports of an employee. If the data is represented in a way that is not hierarchical, you must build a hierarchical representation of the data.

When you set the ItemsControl.ItemTemplate property and if the ItemsControl generates an ItemsControl for each child item, then the child ItemsControl uses the same ItemTemplate as the parent. For example, if you set the ItemTemplate property on a data-bound TreeView, each TreeViewItem that is generated uses the DataTemplate that was assigned to the ItemTemplate property of the TreeView.

The HierarchicalDataTemplate enables you to specify the ItemsSource for a TreeViewItem, or any HeaderedItemsControl, on the data template. When you set the HierarchicalDataTemplate.ItemsSource property, that value is used when the HierarchicalDataTemplate is applied. By using a HierarchicalDataTemplate, you can recursively set the ItemsSource for each TreeViewItem in the TreeView.

Example

The following example demonstrates how to bind a TreeView to hierarchical data and use a HierarchicalDataTemplate to specify the ItemsSource for each TreeViewItem. The TreeView binds to XML data that represents the employees in a company. Each Employee element can contain other Employee elements to indicate who reports to whom. Because the data is recursive, the HierarchicalDataTemplate can be applied to each level.

<Page 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Page.Resources>
    <XmlDataProvider x:Key="myCompany" XPath="Company/Employee">
      <x:XData>
        <Company xmlns="">
          <Employee Name="Don Hall">
            <Employee Name="Alice Ciccu">
              <Employee Name="David Pelton">
                <Employee Name="Vivian Atlas"/>
              </Employee>
              <Employee Name="Jeff Price"/>
              <Employee Name="Andy Jacobs"/>
            </Employee>
            <Employee Name="Bill Malone">
              <Employee Name="Maurice Taylor"/>
              <Employee Name="Sunil Uppal"/>
              <Employee Name="Qiang Wang"/>
            </Employee>
          </Employee>
        </Company>
      </x:XData>
    </XmlDataProvider>

    <!-- Bind the HierarchicalDataTemplate.ItemsSource property to the employees under
         each Employee element. -->
    <HierarchicalDataTemplate x:Key="EmployeeTemplate" 
                              ItemsSource="{Binding XPath=Employee}">
      <TextBlock Text="{Binding XPath=@Name}" ></TextBlock>
    </HierarchicalDataTemplate>

    <Style TargetType="TreeViewItem">
      <Setter Property="IsExpanded" Value="True"/>
    </Style>
  </Page.Resources>

  <Grid>
    <TreeView ItemsSource="{Binding Source={StaticResource myCompany}}" 
              ItemTemplate="{StaticResource EmployeeTemplate}"/>
  </Grid>
</Page>

See also