Kjara Kjara - 2 months ago 17
C# Question

show a hierarchy similar to file system in tree view

(This questions can be considered a duplicate of WPF Treeview Databinding Hierarchal Data with mixed types .)

I have some classes representing a user library. They look like this:

public class UserLibraryData
{
public IList<Node> Nodes { get; private set; }
...
}

public class Node
{
public IList<Node> SubNodes { get; private set; }
public IList<UserDataEntry> Entries { get; private set; }
public string Name { get; private set; }
...
}

public class UserDataEntry
{
string ViewName { get; private set;}
...
}


So it is like a file system with folders (nodes) and files (entries).

Now I want to represent that data in a TreeView, i.e. all nodes and subnodes should be visible and expandable, and the entries should be visible too. I wrote a XAML file that has an instance of
UserLibraryData
as its DataContext. For the TreeView, I wrote this:

<TreeView ItemsSource="{Binding Nodes}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding SubNodes}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>


But as expected, it only shows the nodes and subnodes, not the entries. I tried to add another
HierarchicalDataTemplate
to the
TreeViewTemplate
, but it seems I can only define one such template.

So how do I also show the entries of nodes in each layer?

EDIT:

Lets say we have the following UserLibraryData:

Node1 -> contains Node2, Node3 and Entry1, Entry2
Node2 -> contains Entry3, Entry4
Node3 -> contains Node4
Node4 -> contains Entry5
Node5 -> contains nothing


Then I would like to have the view like this (when everything is expanded):

Node1
Node2
Entry3
Entry4
Node3
Node4
Entry5
Entry1
Entry2
Node5

Answer

I took your data structure and added something missing in order it to be working.

Your issue is the following... When you build your HierarchicalDataTemplate, you can't select two lists as ItemsSource. So, you can't tell your template to show both SubNodes and Entries from a Node.

In order to be able to build your TreeView, you have to construct an unique List containing objects of both Entries and SubNodes.

I called it Childrens. (Add this in Nodes Class).

  public List<object> Childrens
    {
        get 
        {
            _childrens = new List<object>();
            foreach (var subNode in SubNodes)
            {
                _childrens.Add(subNode);
            }
            foreach (var userDataEntry in Entries)
            {
                _childrens.Add(userDataEntry);
            }
            return _childrens;
        }
        private set { _childrens = value; }
    }

After this you have to change your XAML.

I declare the templates as ressources, and thanks to the DataTypes, the templates will be resolved by at run time.

We want to show:

  • Name from Class Node.
  • ViewName from Class Entry.
  • Subnodes and Entries included in the Childrens property from Class Node. (Which expose both previous properties).

    <Grid.Resources>
    
        <HierarchicalDataTemplate DataType="{x:Type local:Node}" ItemsSource="{Binding Childrens}">
            <TextBlock Text="{Binding Name}"/>
        </HierarchicalDataTemplate>
    
        <DataTemplate DataType="{x:Type local:UserDataEntry}">
            <TextBlock Text="{Binding ViewName}"/>
        </DataTemplate>
    
    </Grid.Resources>
    

Assuming your DataContext is set to your Class UserLibraryData, you have to declare your TreeView this way :

<TreeView ItemsSource="{Binding Nodes}"/>

And you should have this result :

enter image description here