0

I am trying to make a treeview that represents data from a file. The file data has data packets organized into three different sections: Header Info, Operation Header, and Operation Data. The packets in Header Info and Operation Header are one level deep, while the packets in Operation Data are grouped into lists so I thought it'd be easier to organize by making it go an extra level. That way you could pop open Data, see the lists, and pop those open to see individual data packets.

This is my xaml:

<TreeView ItemsSource="{Binding TreeViewItems}">
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding TreeNodes}">
                    <TextBlock Text="{Binding Name}" />

                    <HierarchicalDataTemplate.ItemTemplate>
                        <HierarchicalDataTemplate ItemsSource="{Binding Children}">
                            <TextBlock Text="{Binding Name}" />
                            
                                    <HierarchicalDataTemplate.ItemTemplate>
                                        <HierarchicalDataTemplate>
                                            <TextBlock Text="{Binding DataPackets.ItemName}"/>                                                 
                                        </HierarchicalDataTemplate>
                                    </HierarchicalDataTemplate.ItemTemplate>

                        </HierarchicalDataTemplate>
                    </HierarchicalDataTemplate.ItemTemplate>

                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>

And here is the code we are trying to bind to the hierarchical datatemplates:

                var childData = new Children();

                result.OperationData.ToList().ForEach(x => childData.DataPackets.Add(x));

                
                if (result.HeaderInfo.Any())
                {
                    TreeViewItems.Add(new TreePair() { TreeNodes = result.HeaderInfoProperties.ToList(), Name = "Header Info" });
                }
                TreeViewItems.Add(new TreePair() { TreeNodes = result.OperationHeaderProperties.ToList(), Name = "Operation Header" });
                TreeViewItems.Add(new TreePair() { TreeNodes = result.OperationDataProperties.ToList(), Children = new List<Children> {childData}, Name = "Operation Data" });

and the classes

public class TreePair
    {
        

        public TreePair()
        {               
            TreeNodes = new List<PropertyInfo>();
            Children = new List<Children>();
        }

        public List<Children> Children { get; set; }

        public List<PropertyInfo> TreeNodes { get; set; }

        public string Name { get; set; }
    }

    public class Children
    {
        public Children()
        {
            DataPackets = new List<DataPacketBase>();
        }

        public string Name { get; set; }

        public List<DataPacketBase> DataPackets { get; set; }
    }

I have the data packets for Header info and operation header showing up, as well as the list names for Operation data but none of the child packets show up. They exist in the Children.DataPackets object.

This is throwing in the output window: BindingExpression path error: 'Children' property not found on 'object'

The second TextBlock is correct, but the Children ItemSource Is not being found, but the list is being filled with items.

enter image description here

Children Name property Missing From Second Level

enter image description here

1 Answer 1

1

The binding won't find Children because it is looking for it on a PropertyInfo object. Children and TreeNodes are siblings in the tree, there is no Child/Parent relationship between the two so the HierarchicalDataTemplate is broken when it tries to find the Children object that belongs to PropertyInfo object.

If your object hierarchy is correct then you'll need a CompositeCollection that can combine the TreeNodes and Children objects into a single collection.

    private CompositeCollection _treeNodeChildCollections;
    public CompositeCollection TreeNodeChildCollections
    {
        get
        {
            if (_treeNodeChildCollections == null)
            {
                _treeNodeChildCollections = new CompositeCollection();
                var cc1 = new CollectionContainer();
                cc1.Collection = Children;
                var cc2 = new CollectionContainer();
                cc2.Collection = TreeNodes;

                _treeNodeChildCollections.Add(cc1);
                _treeNodeChildCollections.Add(cc2);
            }

            return _treeNodeChildCollections;
        }
    }

Then bind to that in the xaml.

    <TreeView ItemsSource="{Binding TreeViewItems}">
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding TreeNodeChildCollections}">
                <TextBlock Text="{Binding Name}" />
                <HierarchicalDataTemplate.ItemTemplate>
                    <HierarchicalDataTemplate ItemsSource="{Binding DataPackets}">
                        <TextBlock Text="{Binding Name}"/>
                        <HierarchicalDataTemplate.ItemTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding ItemName}"/>
                            </DataTemplate>
                        </HierarchicalDataTemplate.ItemTemplate>
                    </HierarchicalDataTemplate>
                </HierarchicalDataTemplate.ItemTemplate>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>
Sign up to request clarification or add additional context in comments.

6 Comments

This almost has it, it shows all three levels, but the 2nd level string "Name is missing"? The first level textblock is bound to a property called Name, the second level textblock should be bound to another property called name, and the third level should be bound to a textblock called ItemName. The second level items are in the treeview, but the names are not displaying.
So which items aren't displaying their Name?
I updated the question with a image at the bottom that shows the second level string Name missing. I should be the name property from Children.
Updated again with second image, Highlighted the item in the Treeview where string is missing. When I expand the second level its shows correctly using your answer. Upvoted your answer.
Sounds to me like the binding to the Children object is correct so the issue has to be specifically with the Name property. Can you debug and confirm that Name has a value?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.