Building a Recursive Tree Structure for WPF TreeView Data Binding
Define the TreeView control in XAML with a HierarchicalDataTemplate to handle the nested structure:
<TreeView x:Name="CategoryTreeView" Height="400" Width="400">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Name}" FontSize="13" Margin="3,0,0,0" VerticalAlignment="Center"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
Create the data model to represent each node, including a collection for child items and a property to link to its parent:
public class CategoryNode
{
public int Id { get; set; }
public string Name { get; set; }
public int ParentId { get; set; }
public ObservableCollection<CategoryNode> Children { get; set; }
public CategoryNode()
{
Children = new ObservableCollection<CategoryNode>();
ParentId = 0; // Root level nodes default to 0
}
}
In the code-behind, populate the control by converting a flat list into a recursive hierarchy using a LINQ-based method:
public partial class HierarchyView : Window
{
public HierarchyView()
{
InitializeComponent();
var flatList = FetchMockCategories();
CategoryTreeView.ItemsSource = ConstructTree(0, flatList);
}
private List<CategoryNode> FetchMockCategories()
{
return new List<CategoryNode>
{
new CategoryNode { Id = 1, Name = "Electronics", ParentId = 0 },
new CategoryNode { Id = 2, Name = "Clothing", ParentId = 0 },
new CategoryNode { Id = 3, Name = "Laptops", ParentId = 1 },
new CategoryNode { Id = 4, Name = "Smartphones", ParentId = 1 },
new CategoryNode { Id = 5, Name = "Gaming Laptops", ParentId = 3 },
new CategoryNode { Id = 6, Name = "Ultrabooks", ParentId = 3 },
new CategoryNode { Id = 7, Name = "Android", ParentId = 4 },
new CategoryNode { Id = 8, Name = "iOS", ParentId = 4 },
new CategoryNode { Id = 9, Name = "Men's Wear", ParentId = 2 },
new CategoryNode { Id = 10, Name = "Women's Wear", ParentId = 2 }
};
}
private List<CategoryNode> ConstructTree(int parentId, List<CategoryNode> sourceNodes)
{
var rootNodes = sourceNodes.Where(n => n.ParentId == parentId).ToList();
var remainingNodes = sourceNodes.Where(n => n.ParentId != parentId).ToList();
foreach (var node in rootNodes)
{
node.Children = new ObservableCollection<CategoryNode>(ConstructTree(node.Id, remainingNodes));
}
return rootNodes;
}
}