3

I am trying the absolute simplest use of HierarchicalDataTemplate to bind nested data to a WPF TreeView. For some reason, the children of my tree are not visible:

                                                enter image description here

Here is the entire XAML:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:src="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525">
    <TreeView Name="ctTree">
        <TreeView.Resources>
            <HierarchicalDataTemplate DataType = "{x:Type src:MyClass}"
                                      ItemsSource = "{Binding Path=Children}">
                <TextBlock Text="{Binding Path=Name}"/>
            </HierarchicalDataTemplate>
        </TreeView.Resources>
    </TreeView>
</Window>

and here’s all of C# behind this, apart from usings and the namespace:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        var collection = new ObservableCollection<MyClass>
        {
            new MyClass { Name = "parent one" },
            new MyClass { Name = "parent two" },
        };
        collection[0].Children.Add(new MyClass { Name = "child one" });
        collection[0].Children.Add(new MyClass { Name = "child two" });
        ctTree.ItemsSource = collection;
    }
}

class MyClass
{
    public string Name { get; set; }
    public ObservableCollection<MyClass> Children
        = new ObservableCollection<MyClass>();
}

Note that the data template does actually apply to the items: the data is taken from the Name property, and if the template didn’t apply would show as "MyClass" instead.

How do I get the children to show? I seem to be doing exactly the same thing as all examples on HierarchicalDataTemplate.

Roman Starkov
  • 59,298
  • 38
  • 251
  • 324

2 Answers2

7

MyClass.Children is a field, not a property. You cannot bind to a field, convert Children field to a property and everything should work then:

class MyClass
{
    public string Name { get; set; }
    public ObservableCollection<MyClass> Children { get; private set; }

    public MyClass()
    {
        Children = new ObservableCollection<MyClass>();
    }
}
max
  • 33,369
  • 7
  • 73
  • 84
  • 1
    But of course! I’ve seen this before with "normal" binding. Just one question now: where is my exception to tell me how I’ve messed up? I wish it didn’t fail quietly like it does... – Roman Starkov Mar 17 '12 at 14:38
  • 1
    "You can accept the answer in 6 minutes", even though I’ve just tested that it works. Thank you max. – Roman Starkov Mar 17 '12 at 14:39
  • 2
    Well, bindings are usually pretty silent when something is wrong, which makes debugging them extremely annoying. If binding doesn't seem to work right, my steps usually are: 1) check for a typo. 2) ensure that property really exists. 3) ensure that DataContext is set correctly and to expected value. 4) add an empty converter to a binding and set a breakpoint inside it to see what's going on. – max Mar 17 '12 at 14:43
  • 2
    @romkyns: [Check the output window in visual studio.](http://blogs.msdn.com/b/wpfsldesigner/archive/2010/06/30/debugging-data-bindings-in-a-wpf-or-silverlight-application.aspx) – H.B. Mar 18 '12 at 04:52
-1

I think Treeview.Resources is the wrong place for that. You want to put your template in Treeview.ItemTemplate.

Brannon
  • 5,324
  • 4
  • 35
  • 83
  • Not necessarily, especially if the source list contains objects of variable type you will want to define the templates in the resources and make them apply implicitly via the `DataType`. – H.B. Mar 18 '12 at 04:53