Click here to Skip to main content
15,305,754 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi everyone,

I've tried databinding to a treeview for the first time but sadly no succes so far. The other control I've tried, a datagrid control, is fully working so I'm not sure what the bug is here. Was wondering if someone here could help me?



The xaml
C#
<TreeView x:Name="tvDepts" Grid.Column="0" HorizontalAlignment="Left" Grid.RowSpan="6" Grid.Row="1" ItemsSource="{Binding AllParentsCB}" >
        <TreeView.Resources>
            <!-- Top level template -->
            <HierarchicalDataTemplate DataType="{x:Type datalocal:Parent}" ItemsSource="{Binding Children}">
                <TextBlock Text="{Binding Name}" />
            </HierarchicalDataTemplate>
            <!-- Child node template -->
            <DataTemplate DataType="{x:Type datalocal:Child}">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="Name: " FontWeight="Bold" />
                    <TextBlock Text="{Binding ChildName}" />
                </StackPanel>
            </DataTemplate>
        </TreeView.Resources>
    </TreeView>



The Viewmodel
C#
        private void SetInitialSettings()
        {
            AllParentsCB.Clear();
            foreach (var item in FillCBParent()) AllParentsCB.Add(item);
            AllChildrenCB.Clear();
            foreach (var item in FillCBChild()) AllChildrenCB.Add(item);
         }

public ObservableCollection<Parent> AllParentsCB { get; } = new ObservableCollection<Parent>();
public ObservableCollection<Children> AllChildrenCB { get; } = new ObservableCollection<Child>(); 
    
            public static List<Parent> FillCBParent()
        {
            using (var context = new EFContext())
            {
                return context.Parents.ToList();
            }
        }
        public static List<Child> FillCBChild()
        {
            using (var context = new EFContext())
            {
                return context.Children.ToList();
            }
        }


The datacontext
public class Parent : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public int ParentID { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Child> Children { get; set; }

}

public class Child : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public int ChildID { get; set; }
    public string ChildName { get; set; }

    public int ParentID { get; set; }
    public Parent Parent { get; set; }

}


What I have tried:

Renaming specific columns to no avail, plenty of tutorials and other forumposts
Posted
Updated 4-May-21 22:36pm
v2
Comments
Gerry Schmitz 4-May-21 12:28pm
   
It's all in the data (which we can't see). Take a "working example" and fit it to your requirements instead inventing your own (non-working) pattern.

1 solution

Try doing the following. Build a class that the Tree can bind to. The only property is a populated list of parents. The list would be normally populated from a database.


C#
public class FamiliesVM
  {
      public List<Parent> FamilyList { get; private set; }
      public FamiliesVM()
      {
          FamilyList = new List<Parent>
          {
              new Parent
              {
                  Id = 1,
                  Name = "A",
                  Children = new List<Child> { new Child { Id=1,Name="AA"},
                         new Child { Id=2,Name="AB"},new Child { Id=3,Name="AC"} }
              },
              new Parent
              {
                  Id = 2,
                  Name = "B",
                  Children = new List<Child> { new Child { Id=4,Name="BA"},
                         new Child { Id=5,Name="BB"},new Child { Id=6,Name="BC"} }
              },
              new Parent
              {
                  Id = 3,
                  Name = "C",
                  Children = new List<Child> { new Child { Id=7,Name="CA"},
                         new Child { Id=8,Name="CB"},new Child { Id=9,Name="CC"} }
              }
          };


      }
  }

The Parent class is defined something like this
C#
public  class Parent
   {
       public string Name { get; set; }
       public int Id { get; set; }
       public List<Child> Children { get; set; }
   }

In the XAML, set the DataContext to FamiliesVM. Have a HierarchicalDataTemplate that defines the source for the node as Parent and the source for the children of the node as the Children property of the Parent. Have a DataTemplate that details how a Child instance should be displayed. Set the TreeView source to the FamilyList property of the FamiliesVM. That should do the trick.

C#
<Window x:Class="FamilyTree.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:FamilyTree"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <local:FamiliesVM />
    </Window.DataContext>
    <DockPanel>
        <DockPanel.Resources>
            <HierarchicalDataTemplate DataType    = "{x:Type local:Parent}"
                                ItemsSource = "{Binding Path=Children}">
                <TextBlock Text="{Binding Path=Name}"/>
            </HierarchicalDataTemplate>
            <DataTemplate DataType="{x:Type local:Child}">
                <TextBlock Text="{Binding Path=Name}"/>
            </DataTemplate>
        </DockPanel.Resources>
        <TreeView>
            <TreeViewItem ItemsSource="{Binding FamilyList}" Header="Parent and Children" />
        </TreeView>
    </DockPanel>
</Window>
   
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900