Krzaku
Krzaku

Reputation: 196

TreeView binding to a class with a list of another class (and so on)

I tried everything but no matter how I configure HierarchicalDataTemplate it always shows only the top level of the collection (StarSystem items and StarSystemName properties)

This is how my TreeView is configured right now:

<TreeView x:Name="StarSystemTreeView" ItemsSource="{Binding StarSystems, ElementName=window}">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding}">
            <TextBlock Text="{Binding Path=StarSystemName}"/>
            <HierarchicalDataTemplate.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Path=Planets}">
                    <TextBlock Text="{Binding Path=PlanetNumber}"/>
                    <HierarchicalDataTemplate.ItemTemplate>
                        <HierarchicalDataTemplate ItemsSource="{Binding Path=Moons}">
                            <TextBlock Text="{Binding Path=MoonNumber}"/>
                            <HierarchicalDataTemplate.ItemTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding Path=MoonMinerals}"/>
                                </DataTemplate>
                            </HierarchicalDataTemplate.ItemTemplate>
                        </HierarchicalDataTemplate>
                    </HierarchicalDataTemplate.ItemTemplate>
                </HierarchicalDataTemplate>
            </HierarchicalDataTemplate.ItemTemplate>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

window is my MainWindow class, in which StarSystems is initialized:

public partial class MainWindow
{
    private ObservableCollection<StarSystem> _starSystems = new ObservableCollection<StarSystem>
    {
        new StarSystem("FooSystem",
            new ObservableCollection<Planet>
            {
                new Planet(1, new ObservableCollection<Moon>
                {
                    new Moon(1, new ObservableCollection<string>
                    {
                        "FooMineral"
                    })
                })
            })
    };

    public ObservableCollection<StarSystem> StarSystems
    {
        get { return _starSystems; }
        set { _starSystems = value; }
    }
}

The 3 classes I want to bind to the TreeView are defined outside of MainWindow class, in the same namespace:

[NotifyPropertyChanged]
public class StarSystem
{
    public StarSystem()
        : this("", new ObservableCollection<Planet>())
    {
    }
    public StarSystem(string starSystemName, ObservableCollection<Planet> planets)
    {
        StarSystemName = starSystemName;
        Planets = planets;
    }

    public string StarSystemName { get; set; }
    public ObservableCollection<Planet> Planets { get; set; }
}

[NotifyPropertyChanged]
public class Planet
{
    public Planet()
        : this(0, new ObservableCollection<Moon>())
    {
    }
    public Planet(int planetNumber, ObservableCollection<Moon> moons)
    {
        PlanetNumber = planetNumber;
        Moons = moons;
    }

    public int PlanetNumber { get; set; }
    public ObservableCollection<Moon> Moons { get; set; }
}

[NotifyPropertyChanged]
public class Moon
{
    public Moon()
        : this(0, new ObservableCollection<string>())
    {
    }
    public Moon(int moonNumber, ObservableCollection<string> moonMinerals)
    {
        MoonNumber = moonNumber;
        MoonMinerals = moonMinerals;
    }

    public int MoonNumber { get; set; }
    public ObservableCollection<string> MoonMinerals { get; set; }
}

This is how it look after starting the application:

I've been trying to figure it out for the past 3 days and I think I've tried every way possible to configure the HierarchicalDataTemplate so I'm probably just doing something wrong...

Upvotes: 0

Views: 258

Answers (1)

Rohit Vats
Rohit Vats

Reputation: 81348

ItemTemplate is bit messed up. You have set ItemSource one hierarchy level down. It should be:

<TreeView x:Name="StarSystemTreeView"
          ItemsSource="{Binding StarSystems, ElementName=window}">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Path=Planets}">
            <TextBlock Text="{Binding Path=StarSystemName}"/>
            <HierarchicalDataTemplate.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Path=Moons}">
                    <TextBlock Text="{Binding Path=PlanetNumber}"/>
                    <HierarchicalDataTemplate.ItemTemplate>
                        <HierarchicalDataTemplate
                                    ItemsSource="{Binding Path=MoonMinerals}">
                            <TextBlock Text="{Binding Path=MoonNumber}"/>
                            <HierarchicalDataTemplate.ItemTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding}"/>
                                </DataTemplate>
                            </HierarchicalDataTemplate.ItemTemplate>
                        </HierarchicalDataTemplate>
                    </HierarchicalDataTemplate.ItemTemplate>
                </HierarchicalDataTemplate>
            </HierarchicalDataTemplate.ItemTemplate>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

Upvotes: 1

Related Questions