WPF TreeView - If I use binding, the ToString() is never called and the text is blank. If I set the items programmatically, it works fine

Viewed 38

The Classes

    public class TreeDiagram : INotifyPropertyChanged
    {
        public string CategoryName
        {...}

        public ObservableCollection<ImageInfo> DiagramsTRV
        {...}

        public class ImageInfo : INotifyPropertyChanged
    {
        public string Category
        { ...}

        public override string ToString()
        {
            return DisplayName;
        }

        public string DisplayName
        {...}

        public ObservableCollection<TreeDiagram> TreeDiagrams {...}
        <StackPanel Orientation="Vertical">
        <StackPanel Orientation="Horizontal">
            <StackPanel Orientation="Vertical">
                <TextBlock Text="Binding"/>
                <TreeView  x:Name="trvDiagrams" Width="300" Height="400" ItemsSource="{Binding TreeDiagrams}" HorizontalAlignment="Left">
                <TreeView.ItemTemplate>
                    <HierarchicalDataTemplate DataType="x:Type local:TreeDiagram" ItemsSource="{Binding DiagramsTRV, UpdateSourceTrigger=PropertyChanged}">
                        <TextBlock Width="250" Text="{Binding CategoryName, UpdateSourceTrigger=PropertyChanged}"/>
                    </HierarchicalDataTemplate>
                </TreeView.ItemTemplate>
            </TreeView>
            </StackPanel>
            <StackPanel Orientation="Vertical">
                <TextBox Text="No Binding"/>
                <TreeView x:Name="trvNoBind" Width="300" Height="400" HorizontalAlignment="Right">
                </TreeView>
            </StackPanel>
        </StackPanel>
    </StackPanel>

If I use binding, the Category Name is displayed, the The TreeDiagram ToString() is never called and the dropdown items are blank.

If I load the tree programmatically with the same data - everything is fine.

But for a variety of reasons, I need to use binding. I have tried an IValueConverter to take the collection of objects and return a collection of strings - no joy. Any suggestions as to what I am doing wrong?

Binding VS No Binding

1 Answers

Your template is incomplete. You must define a template for the child nodes too. You must either set the HierarchicalDataTemplate.ItemsTemplate property accordingly or define an implicit template e.g. in the ResourceDictionary of the TreeView.

You want to display a recursive or hierarchical data structure. Since your structure consists of different data types, you must define a template for each level.

Note that UpdateSourceTrigger.PropertyChanged is the default value of Binding.UpdateSourceTrigger and is therefore not explicitly required.

<TreeView>
  <TreeView.Resources>

    <!-- 
         Because 'ImageInfo' has no children, 
         define a 'DataTemplate' (instaed of another 'HierarchicalDataTemplate').
         If this 'DataTemplate' wasn't implicit, you would have to explicitly assign it
         to the parent's 'HierarchicalDataTemplate.ItemTemplate' property. 
    -->
    <DataTemplate DataType="{x:Type local:TreeDiagram}">
      <TextBlock Text="{Binding}" />  <== Force the call to 'object.ToString' by binding to the object itself
    </DataTemplate>

    <HierarchicalDataTemplate DataType="{x:Type local:TreeDiagram}"
                              ItemsSource="{Binding DiagramsTRV}">
      <TextBlock Text="{Binding CategoryName}" />
    </HierarchicalDataTemplate>
  </TreeView.Resources>
</TreeView>
Related