← Все вопросы
Как построить иерархическое дерево в TreeView (WPF) с привязкой данных?
6
Хочу показать дерево категорий (категория → подкатегории → товары) в WPF через TreeView. С плоским списком разобрался, а как сделать раскрывающиеся узлы из вложенных коллекций? Видел HierarchicalDataTemplate, но не понял, как им пользоваться.
2 ответа
11
✓ Принятый ответ — помог автору
Для иерархии в TreeView используется именно HierarchicalDataTemplate — это шаблон, который знает, где у узла лежат его дочерние элементы.
Модель с вложенностью:
public class Node
{
public string Title { get; set; } = "";
public ObservableCollection<Node> Children { get; } = new();
}
public class TreeVm
{
public ObservableCollection<Node> Roots { get; } = new()
{
new Node
{
Title = "Электроника",
Children =
{
new Node { Title = "Телефоны" },
new Node { Title = "Ноутбуки" }
}
}
};
}
XAML:
<TreeView ItemsSource="{Binding Roots}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Title}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
Как это читается:
ItemsSource="{Binding Roots}"у TreeView — корневые узлы;HierarchicalDataTemplate.ItemsSource="{Binding Children}"— где брать детей каждого узла (вот это и делает дерево рекурсивным);- содержимое шаблона (
TextBlock) — как отрисовать сам узел.
WPF применяет этот же шаблон к детям, потом к их детям и так далее — глубина неограниченна.
Полезные мелочи:
- чтобы раскрыть узел программно/по привязке, заведите свойство
IsExpandedв модели и привяжите черезItemContainerStyle; - для разных типов узлов (категория vs товар) можно задать несколько
HierarchicalDataTemplate/DataTemplateс указаниемDataType.
4
Если у вас узлы разных типов (например, Папка и Файл), удобно завести отдельные шаблоны по типу данных и положить их в ресурсы:
<TreeView ItemsSource="{Binding Roots}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Folder}"
ItemsSource="{Binding Items}">
<TextBlock Text="{Binding Name}" FontWeight="Bold"/>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type local:FileItem}">
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</TreeView.Resources>
</TreeView>
WPF сам выберет нужный шаблон по типу элемента — это чистый и расширяемый подход.
Ваш ответ
Войдите, чтобы ответить на вопрос.