The good news is that you do a lot more work here than you need, which is probably due to the fact that you have problems.
The bad news is that you have to really learn a little more about WPF in order to understand this correctly and come up with a good approach, clean and concise. I will try to point you in the right direction.
First, you have to break away from the ItemsControl. This is a really powerful class and is the base class of many everyday controls that you will use in your WPF application. You should understand how binding any collection (IEnumerable, IList, IBindingList, etc.) to the ItemsSource property of the ItemsControl element will lead to the creation of child elements.
Then you should understand (if you don't already know this) how data types are converted to user interface elements through DataTemplates. This is a simple but powerful concept.
Then you should experiment with the small extension mentioned above, namely HeaderedItemsControl and HierarchicalDataTemplate. This will give you all the tools you need to use TreeView in the form you want.
In no case do you need to create any TreeViewItems in C # code. If you can get the underlying data objects to display the hierarchy that you want to display (regardless of whether each node is a simple text label or a data network), you can create hierarchical data templates for all levels and support WPF by linking everything and creating TreeViewItems for you .
EDIT
I have questions about your edited question:
- What is the difference between
Root and Nodes ? - Do you have a class hierarchy that models the relationship between nodes? If so, just use it, and not copy objects to
Root and Nodes instances. I will give you an example.
Suppose you have Customer that put Order s, and each order has Item s.
public class Customer { public string Name { get; set; } public IEnumerable<Order> Orders { get; set; } } public class Order { public DateTime PurchaseDate { get; set; } public IEnumerable<OrderItem> Items { get; set; } } public class OrderItem { public string ProductName { get; set; } public int Quantity { get; set; } public double UnitPrice { get; set; } public double TotalPrice { get; set; } }
The above types represent a hierarchy. If you have such a structure, you can bind it directly to the user interface. You do not need to create Root or Node objects. This is the WPF way :)
(Note that if you do not have the above class hierarchy, you can customize it specifically for use in the user interface. Learn more about the MVVM template if you are interested.)
In your XAML, you define a TreeView as:
<TreeView x:Name="_treeView" ItemsSource="{Binding}"> <TreeView.Resources> <HierarchicalDataTemplate DataType="{x:Type data:Customer}" ItemsSource="{Binding Path=Orders}"> <TextBlock Text="{Binding Name}"/> </HierarchicalDataTemplate> <DataTemplate DataType="{x:Type data:Order}"> <StackPanel> <TextBlock Text="{Binding PurchaseDate}"/> <ListView ItemsSource="{Binding Items}"> <ListView.View> <GridView> <GridViewColumn DisplayMemberBinding="{Binding ProductName}" /> <GridViewColumn DisplayMemberBinding="{Binding Quantity}" /> <GridViewColumn DisplayMemberBinding="{Binding UnitPrice}" /> <GridViewColumn DisplayMemberBinding="{Binding TotalPrice}" /> </GridView> </ListView.View> </ListView> </StackPanel> </DataTemplate> </TreeView.Resources> </TreeView>
And in encoding, you would do something like this:
_treeView.DataContext = customers;