Click here to Skip to main content
15,887,477 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
[no name] 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>
 
Share this answer
 
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