Table of Contents

Привязка к иерархическим данным

В типичном иерархическом источнике данных бизнес-объект имеет свойство, в котором хранится коллекция дочерних объектов данных. Два подхода позволяют вам предоставлять дочерние данные в контролы TreeList и TreeView в режиме иерархической привязки:

Родительский и дочерний объекты данных могут быть разных типов, но у них должен быть общий набор идентичных свойств, которые контрол TreeList отображает в виде столбцов.

Динамическая загрузка данных

При привязке к иерархическому источнику данных TreeList и TreeView контролируют загрузку узлов по требованию по умолчанию: дочерние узлы динамически загружаются при развертывании родительского узла.

Установите для свойства AllowDynamicDataLoading значение false, чтобы загрузить все узлы одновременно после привязки контрола к источнику данных.

Если вы используете динамическую загрузку узлов, контролы TreeList и TreeView не имеют доступа к узлам (и их нижележащим данным), которые не были загружены. Это накладывает следующие ограничения на функции проверки узлов и фильтрации/поиска:

  • Когда вы проверяете родительский узел в рекурсивном режиме (см. AllowRecursiveNodeChecking), контрол проверяет этот узел вместе с загруженными в данный момент дочерними узлами. Контрол не проверяет дочерние узлы, которые не были загружены.

  • Когда вы выполняете поиск данных во встроенном окне поиска или фильтруете данные с помощью строки автоматической фильтрации, контрол выполняет поиск данных только по загруженным в данный момент узлам.

Путь к дочерним данным

Один из способов предоставить дочерние данные в контрол TreeList/TreeView заключается в указании имени свойства, которое хранит дочерние данные в бизнес-объекте. Используйте свойство ChildrenFieldName для этой цели. Например, если бизнес-объект хранит дочерние данные в коллекции Items, установите для свойства ChildrenFieldName значение "Items".

Вам также необходимо присвоить свойству HasChildrenFieldName имя свойства, которое возвращает true, если бизнес-объект имеет дочерние данные, и false, в противном случае. Эта информация необходима для отображения или скрытия кнопок расширения узла. Если вы не укажете свойство HasChildrenFieldName, контрол отображает кнопки расширения для дочерних узлов до тех пор, пока пользователь не попытается развернуть эти узлы.

В следующем примере показано, как привязать контрол TreeList к данным. Объект Employee в примере содержит коллекцию Subordinates, которая содержит дочерние элементы. Свойство ChildrenFieldName указывает имя свойства (строка "Subordinates"), в котором хранятся дочерние данные.

xmlns:mxtl="clr-namespace:Eremex.AvaloniaUI.Controls.TreeList;assembly=Eremex.Avalonia.Controls"
...
<mxtl:TreeListControl Grid.Column="0" Width="400" Name="treeList1" >
    <mxtl:TreeListControl.Columns>
        <mxtl:TreeListColumn Name="colName" FieldName="Name" Header="Name" />
        <mxtl:TreeListColumn Name="colBirthdate" FieldName="Birthdate" Header="Birthdate"/>
    </mxtl:TreeListControl.Columns>
</mxtl:TreeListControl>
using CommunityToolkit.Mvvm.ComponentModel;

Employee p1 = new Employee() { Name = "Mark Douglas", Birthdate=new DateTime(1990, 01, 5) };
Employee p2 = new Employee() { Name = "Mary Watson", Birthdate = new DateTime(1985, 12, 17) };
Employee p3 = new Employee() { Name = "Alex Wude", Birthdate = new DateTime(2000, 10, 7) };
Employee p4 = new Employee() { Name = "Sam Louis", Birthdate = new DateTime(1975, 8, 27) };
Employee p5 = new Employee() { Name = "Dan Miller", Birthdate = new DateTime(1981, 3, 6) };
p1.Subordinates.Add(p2);
p1.Subordinates.Add(p3);
p2.Subordinates.Add(p4);
p3.Subordinates.Add(p5);

ObservableCollection<Employee> employees = new ObservableCollection<Employee>() { p1 };

treeList1.ChildrenFieldName = "Subordinates";
treeList1.HasChildrenFieldName = "HasChildren";

treeList1.ItemsSource = employees;

public partial class Employee : ObservableObject
{
    [ObservableProperty]
    public string name="";

    [ObservableProperty]
    public DateTime? birthdate=null;

    public ObservableCollection<Employee> Subordinates { get; } = new();

    public bool HasChildren { get { return Subordinates.Count > 0; } }
}

Селектор дочерних данных

Другим подходом к предоставляет дочерние данные в режиме иерархической привязки является реализация selector. Селектор указывает, доступны ли дочерние данные в бизнес-объекте, и возвращает эти дочерние данные по запросу. Контрол TreeList/TreeView использует информацию, предоставленную селектором, для создания дочерних узлов и рисования кнопок расширения узлов.

Используйте свойство ChildrenSelector, чтобы назначить селектор вашему контролу. Селектор - это объект, который реализует интерфейс ITreeListChildrenSelector:

public interface ITreeListChildrenSelector
{
	// The method should return whether a business object has child data. 
    // The control uses this information to display or hide node expand buttons.
    bool HasChildren(object item) => true;
    // The method should return child objects for a business object.
	IEnumerable? SelectChildren(object item);
}

В следующем примере создается селектор (MyTreeListChildrenSelector), который предоставляет информацию о дочерних данных для контрола TreeList.

xmlns:mxtl="clr-namespace:Eremex.AvaloniaUI.Controls.TreeList;assembly=Eremex.Avalonia.Controls"
...
<Grid RowDefinitions="Auto, Auto, Auto, Auto" ColumnDefinitions="400, *">
    <Grid.Resources>
        <local:MyTreeListChildrenSelector x:Key="mySelector" />
    </Grid.Resources>

    <mxtl:TreeListControl Grid.Column="0" Name="treeList2"
     ChildrenSelector="{StaticResource mySelector}">
        <mxtl:TreeListControl.Columns>
            <mxtl:TreeListColumn Name="colName1" FieldName="Name" />
            <mxtl:TreeListColumn Name="colBirthdate1" FieldName="Birthdate"/>
        </mxtl:TreeListControl.Columns>
    </mxtl:TreeListControl>
</Grid>
using CommunityToolkit.Mvvm.ComponentModel;

Employee p1 = new Employee() { Name = "Mark Douglas", Birthdate=new DateTime(1990, 01, 5) };
Employee p2 = new Employee() { Name = "Mary Watson", Birthdate = new DateTime(1985, 12, 17) };
Employee p3 = new Employee() { Name = "Alex Wude", Birthdate = new DateTime(2000, 10, 7) };
Employee p4 = new Employee() { Name = "Sam Louis", Birthdate = new DateTime(1975, 8, 27) };
Employee p5 = new Employee() { Name = "Dan Miller", Birthdate = new DateTime(1981, 3, 6) };
p1.Subordinates.Add(p2);
p1.Subordinates.Add(p3);
p2.Subordinates.Add(p4);
p3.Subordinates.Add(p5);

ObservableCollection<Employee> employees = new ObservableCollection<Employee>() { p1 };

treeList2.ItemsSource = employees;

public class MyTreeListChildrenSelector : ITreeListChildrenSelector
{
    public bool HasChildren(object? item) => (item as Employee).HasChildren;
    public IEnumerable? SelectChildren(object? item) => (item as Employee).Subordinates;
}

public partial class Employee : ObservableObject
{
    [ObservableProperty]
    public string name="";

    [ObservableProperty]
    public DateTime? birthdate=null;

    public ObservableCollection<Employee> Subordinates = new();

    public bool HasChildren { get { return Subordinates.Count > 0; } }
}

Смотрите также



* Эта страница была создана автоматически с помощью сервиса машинного перевода Яндекс Переводчик.