WPF Treeview – Binding to a collection with different depths, and styling differently – Education Career Blog

Apologies for the long post — Read a few threads about this, but still find it hard to implement. Basically, I have a collection of objects, defined as:

public class LibData
{
    public string Name { get; set; }
    ObservableCollection<LibObject> _list;
    public ObservableCollection<LibObject> List { get { return _list; } }

    public LibData(string name, LibDataType type)
    {
        this.Name = name;
        _list = new ObservableCollection<LibObject>();
    }
}

and the object:

public class LibObject
{
    public string Name { get; set; }

    public LibObject(string name)
    {
        this.Name = name;
    }
}

My main problem is in the XAML, and styling this TreeView. I need to have a specific style for a “root” item, and a specific style for a “leaf”. Thing is, that one item in the bound list is “Root->Leaf”, and another is “Root->Child->Leaf”.
I tried this:

<TreeView x:Name="myTree" ItemsSource="{x:Static local:myDataList}">
     <TreeView.ItemTemplate>
         <HierarchicalDataTemplate ItemsSource="{Binding Path=List}" >
             <Grid>
                 <StackPanel Orientation="Horizontal">
                      <TextBlock Text="{Binding Path=Name}" />
                      <CheckBox IsChecked="True" Content="HeaderCheckbox"/>
                 </StackPanel>
             </Grid>
         <HierarchicalDataTemplate.ItemTemplate >
              <DataTemplate>
                  <Grid>
            <StackPanel Orientation="Horizontal">
                <CheckBox IsChecked="True" Content="LeafCheckbox" />
                <TextBlock Text="{Binding Path=Name}"/>
            </StackPanel>
                  </Grid>
              </DataTemplate>
          </HierarchicalDataTemplate.ItemTemplate>
      </HierarchicalDataTemplate>
  </TreeView.ItemTemplate>

This obviously works fine for the “Root->Leaf” item, but not for the “Root-Child-Leaf”.
The XAML implementation seems to be more of a “hard coded” solution, where I know that the item layout is always “Root->Leaf” – how do I make this dynamic?
Again, I have seen solutions to different levels (including using converters), but the problem i’m having is that I need specific styles to root and leaf and nothing for levels in between.
I’m wondering if I’m looking at this completely wrong …

,

Easy way to do this. Pull the DataTemplates out of the TreeView and put them in the resources section. Specify the DataType property for each DataTemplate, but do not include a key. The ItemTemplateSelector (a property of type DataTemplateSelector) on the TreeView will do the magic of using whichever DataTemplate suits the correct item type.

Create a HierarchicalDataTemplate for types Root and Child, and a DataTemplate for type Leaf.

Something like this:

<Window.Resources>
    <ResourceDictionary>

        <DataTemplate DataType="{x:Type local:Leaf}">
            <Grid>
                <StackPanel Orientation="Horizontal">
                    <CheckBox IsChecked="True" Content="LeafCheckbox" />
                    <TextBlock Text="{Binding Path=SomeValue}"/>
                </StackPanel>
            </Grid>
        </DataTemplate>

        <HierarchicalDataTemplate DataType="{x:Type local:Child}"
                                  ItemsSource="{Binding Children}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="Child " />
                <TextBlock Text="{Binding Path=SomeValue}" />
            </StackPanel>
        </HierarchicalDataTemplate>

        <HierarchicalDataTemplate DataType="{x:Type local:Root}"
                                  ItemsSource="{Binding Children}">
            <Grid>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="Root " />
                    <TextBlock Text="{Binding Path=SomeValue}" />
                </StackPanel>
            </Grid>
        </HierarchicalDataTemplate>

    </ResourceDictionary>
</Window.Resources>

<Grid>
    <TreeView x:Name="myTree" ItemsSource="{Binding}" />
</Grid>

Leave a Comment