larzz11
larzz11

Reputation: 1032

WPF TreeView with child nodes under distinct categories

Given the following class Foo

class Foo {
    public string Property1 { get; set; }
    public string Property2 { get; set; }
}

Given a List<Foo> where Property1 is a category, so multiple instances of Foo in the collection have the same value for Property1. Property2 is unique in this case, but that is not relevant.

I want to show the collection of Foo in a TreeView in WPF, where for every Distinct Property1 it shows a node (with the value of Property1 as the header). And as child items of that node it should have all the instances of Foo with that Property1, and it should have Property2 as the header.

So far I have tried the HierarchicalDataTemplate approach (would prefer) and the code behind, but neither seem to have the result I want. Here is the code behind I tried:

private void ReloadTree() {
    var uniqueProperty1 = foos
        .Select(f => f.Property1)
        .Distinct();

    var result = new List<TreeViewItem>();
    
    foreach (var prop1 in uniqueProperty1) {
        var item = new TreeViewItem();
        item.Header = name;
        item.IsExpanded = false;
    
        var attributes = new List<Foo>();

        foreach (var foo in attributes) {
            var subItem = new TreeViewItem();
            subItem.Header = foo.Property2;

            item.Items.Add(subItem);
        }

        bindingsTree.Items.Add(item);
    }
}

Where foos is the collection of Foo, and bindingsTree is the TreeView. Any help would be really appreciated!

Edit

To clarify given the following list of foos:

var list = new List<Foo>()
{
    new Foo() { Property1 = "category1", Property2 = "A" },
    new Foo() { Property1 = "category1", Property2 = "B" },
    new Foo() { Property1 = "category2", Property2 = "C" },
    new Foo() { Property1 = "category2", Property2 = "D" },
};

The result should look like this:

+category1
    - A
    - B
+category2
    - C
    - D

Upvotes: 3

Views: 536

Answers (1)

mm8
mm8

Reputation: 169420

Create an hierarchical model type:

class FooViewModel
{
    public string Category { get; set; }
    public IEnumerable<FooViewModel> Children { get; set; }
}

...and group foos by Property1:

private void ReloadTree()
{
    var categories = foos
        .GroupBy(x => x.Property1)
        .Select(x => new FooViewModel { Category = x.Key, Children = x.Select(y => new FooViewModel() { Category = y.Property2 }).ToArray() })
        .ToArray();

    bindingsTree.ItemsSource = categories;
}

XAML:

<TreeView x:Name="bindingsTree">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Children}">
            <TextBlock Text="{Binding Category}" />
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

Upvotes: 2

Related Questions