Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TreeView with nested List

I want to display some objects in a treeview, but so far unfortunately without success.

I've a ObservableCollection <ICustom> of objects: Settings.ListOfCustomers

The interface of the object ICustom:

int Id { get; }
int age { get; }
CustomerType CustomerType { get; }
ObservableCollection<IValue> ListOfValues { get; }

The ObservableCollection<IValue> ListOfValues has also some properties like:

String Name { get; }

My View:

<TreeView ItemsSource="{Binding ListOfCustomers, UpdateSourceTrigger=PropertyChanged}">

    <TreeView.Resources>

        <HierarchicalDataTemplate DataType="{x:Type customerConfig:ICustomer}">
            <TextBlock Text="{Binding Id}"/>
        </HierarchicalDataTemplate>

        <HierarchicalDataTemplate DataType="{x:Type valueConfig:IValue}" ItemsSource="{Binding ListOfValues}">
            <StackPanel>
                <TextBlock Text="{Binding Name}"/>
            </StackPanel>
        </HierarchicalDataTemplate>

    </TreeView.Resources>


</TreeView>

Question: How can I display display these objects in a TreeView? My approach (see "My View") does not work.

like image 287
Philies Avatar asked Sep 01 '17 04:09

Philies


2 Answers

To Question 1: ObservableCollections have the advantage, that all notifications to the view are done automatically. So you do not have to worry about NotifyPropertyChanged events for adding/removing objects from the collection.

To Question 2: Your ViewModel is your DataContext? I do not see where there is a property ObservableCollection<ICustomer>? Can you provide more detail about relationships in this classes?

EDIT:

Based on the answer of mm8, the x:Type attribute should be of a concrete type. So the code should look something like this:

I suggest that you have an ObservableCollection<ICustomer> ListOfCustomers in your ViewModel, then you can bind in the view:

    <TreeView ItemsSource="{Binding ListOfCustomers}">
        <TreeView.Resources>
            <HierarchicalDataTemplate DataType="{x:Type Customer}">
                <TextBlock Text="{Binding Id}"/>
            </HierarchicalDataTemplate>

            <HierarchicalDataTemplate DataType="{x:Type modSettings:Value}"
                              ItemsSource="{Binding ListOfValues}">
                <TextBlock Text="{Binding Name}"/>
            </HierarchicalDataTemplate>
        </TreeView.Resources>
    </TreeView>

I think this thread provides a more detailed solution for your problem: Implement WPF treeview with different Parent Nodes a well as different child nodes?

EDIT2:

I changed my code a bit, to match your requirements. This should display all nodes:

<TreeView ItemsSource="{Binding ListOfCustomers}" >
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding Path=ListOfValues}" DataType="{x:Type Customer}">
                <HierarchicalDataTemplate.ItemTemplate>
                    <HierarchicalDataTemplate DataType="{x:Type modSettings:Value}">
                        <TextBlock Text="{Binding Path=Name}"/>
                    </HierarchicalDataTemplate>
                </HierarchicalDataTemplate.ItemTemplate>
                <TextBlock Text="{Binding Path=Id}"/>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>
like image 193
Eike B Avatar answered Oct 29 '22 00:10

Eike B


I have converted all Lists to ObservableCollection, also the nested Lists. Is this necessary and correct?

It is not necessary unless you intend to add items to the collection dynamically at runtime. Then you need to use an ObservableCollection<T> for these to automatically show up in the TreeView. Othwerwise you might as well use a List<T>.

How can I display display these objects in a TreeView?

You get the error message because you add the templates to the Items property of the TreeView. They should be added to the Resources property, i.e. you need to add a <TreeView.Resources> element.

You should also read this:

Why can't a DataTemplate bind to an interface when that DataTemplate was explicitly returned from a DataTemplateSelector?

Templates with the DataType property set to an interface type are not applied. So you should either define a HierarchicalDataTemplate per concrete type or use a DataTemplateSelector.

like image 34
mm8 Avatar answered Oct 29 '22 02:10

mm8