← Все вопросы

Как построить иерархическое дерево в TreeView (WPF) с привязкой данных?

Задан 32 месяца назад1.5к просмотров2 ответа
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 сам выберет нужный шаблон по типу элемента — это чистый и расширяемый подход.

Ваш ответ

Войдите, чтобы ответить на вопрос.
Поддержать проект