Диапазоны (Бэнды)¶
Вы можете использовать диапазоны для визуального объединения столбцов вместе. Контрол TreeListControl отображает диапазоны как дополнительные заголовки над заголовками столбцов. Как заголовки диапазонов, так и заголовки столбцов могут содержать текст, изображения или пользовательское содержимое. Вы также можете создавать иерархические диапазоны с неограниченным количеством уровней вложенности.
На следующем изображении показан контрол TreeList с четырьмя диапазонами: 'Employee', 'Details', 'Contact' и 'Address':

Следующие подходы позволяют генерировать диапазоны столбцов:
- Создание диапазонов вручную
- Создание диапазонов из источника диапазонов
- Создание диапазонов на основе атрибутов DataAnnotation (для автоматически генерируемых столбцов)
Создание диапазонов вручную¶
Выполните следующие шаги для ручного создания диапазонов:
- 
Создайте объекты диапазонов (экземпляры класса TreeListBand) и добавьте их в коллекциюTreeListControl.Bands.Присвойте созданным диапазонам уникальные имена с помощью свойства TreeListBand.BandName.<mxtl:TreeListControl.Bands> <mxtl:TreeListBand BandName="Employee" HeaderHorizontalAlignment="Center"/> <mxtl:TreeListBand BandName="Details" HeaderHorizontalAlignment="Center"/> </mxtl:TreeListControl.Bands>Вы можете создать иерархическую структуру диапазонов. Чтобы создать вложенные диапазоны: - В code-behind: Добавьте диапазоны в коллекцию TreeListBand.Bands.
- В XAML: Определите вложенные диапазоны непосредственно между открывающим и закрывающим тегами TreeListBand.
 <mxtl:TreeListBand BandName="Details" HeaderHorizontalAlignment="Center"> <mxtl:TreeListBand BandName="DetailsAddress" Header="Address" HeaderHorizontalAlignment="Center"/> <mxtl:TreeListBand BandName="DetailsContact" Header="Contact" HeaderHorizontalAlignment="Center"/> </mxtl:TreeListBand>Свойство TreeListBand.Headerпозволяет указать пользовательское содержимое (например, пользовательский текст) для диапазона. Если это свойство не задано, в заголовке диапазона отображается значение свойстваTreeListBand.BandName.
- В code-behind: Добавьте диапазоны в коллекцию 
- 
Свяжите столбцы с конкретными диапазонами, установив для каждого столбца свойство TreeListColumn.BandNameв соответствие с именем диапазона (TreeListBand.BandName).<mxtl:TreeListControl.Columns> <mxtl:TreeListColumn Width="150" FieldName="Name" BandName="Employee"/> <mxtl:TreeListColumn Width="*" FieldName="City" BandName="DetailsAddress"/> <mxtl:TreeListColumn Width="*" FieldName="Phone" BandName="DetailsContact"/> <!-- ... --> </mxtl:TreeListControl.Columns>
Столбцы располагаются в контроле TreeListControl в соответствии с их свойствами TreeListColumn.VisibleIndex. Контрол не переупорядочивает столбцы автоматически, чтобы сгруппировать их по диапазонам.
См. Порядок столбцов и диапазонов
Связанный API¶
- TreeListBandclass — Инкапсулирует диапазон столбцов.
- TreeListBand.BandName— Уникальное имя, используемое для идентификации диапазона и связи его со столбцами.
- TreeListColumn.BandName— Имя диапазона, связанного со столбцом. Это значение соответствует значению свойства- TreeListBand.BandName.
- TreeListControl.Bands— Коллекция корневых диапазонов.
- TreeListBand.Bands— Коллекция дочерних диапазонов для этого диапазона.
Пример - Создание диапазонов столбцов в контроле TreeList¶
Следующий пример создает диапазоны и назначает их столбцам TreeList, как показано на изображении ниже:
- Диапазоны "Employee", "Job", "Personal", "Address" и "Contact" связаны со столбцами TreeList.
- Диапазон "Details" содержит два вложенных диапазона ("Address" и "Contact"). Этот диапазон не связан напрямую со столбцами.
Каждому диапазону присвоено уникальное имя с помощью свойства TreeListBand.BandName. Чтобы связать столбцы с определенным диапазоном, свойство TreeListColumn.BandName устанавливается в значение BandName целевого диапазона.
Свойство TreeListControl.Bands определяет структуру диапазонов. Чтобы создать вложенные диапазоны, определите их как дочерние элементы родительского диапазона.
<!-- MainWindow.axaml file -->
<mx:MxWindow xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="using:TreeListColumnBands.ViewModels"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:mx="https://schemas.eremexcontrols.net/avalonia"
        xmlns:mxtl="https://schemas.eremexcontrols.net/avalonia/treelist"
        xmlns:mxe="https://schemas.eremexcontrols.net/avalonia/editors"
        mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
        x:Class="TreeListColumnBands.Views.MainWindow"
        x:DataType="vm:MainWindowViewModel"
        Icon="/Assets/EMXControls.ico"
        Title="TreeListColumnBands">
    <Design.DataContext>
        <!-- This only sets the DataContext for the previewer in an IDE-->
        <vm:MainWindowViewModel/>
    </Design.DataContext>
    <mxtl:TreeListControl Name="employeeTreeList" AutoGenerateColumns="False"
                          ItemsSource="{Binding Employees}"
                          ChildrenFieldName="Subordinates"
                          HasChildrenFieldName="HasSubordinates"
                          >
        <mxtl:TreeListControl.Bands>
            <mxtl:TreeListBand BandName="Employee" HeaderHorizontalAlignment="Center"/>
            <mxtl:TreeListBand BandName="Job" HeaderHorizontalAlignment="Center"/>
            <mxtl:TreeListBand BandName="Personal" HeaderHorizontalAlignment="Center"/>
            <mxtl:TreeListBand BandName="Details" HeaderHorizontalAlignment="Center" HeaderToolTip="Contact and location information">
                <mxtl:TreeListBand BandName="DetailsAddress" Header="Address" HeaderHorizontalAlignment="Center"/>
                <mxtl:TreeListBand BandName="DetailsContact" Header="Contact" HeaderHorizontalAlignment="Center"/>
            </mxtl:TreeListBand>
        </mxtl:TreeListControl.Bands>
        <mxtl:TreeListControl.Columns>
            <mxtl:TreeListColumn Width="150" FieldName="Name" BandName="Employee"/>
            <mxtl:TreeListColumn Width="*" FieldName="Position" BandName="Job"/>
            <mxtl:TreeListColumn Width="*" FieldName="Salary" BandName="Job">
                <mxtl:TreeListColumn.EditorProperties>
                    <mxe:TextEditorProperties DisplayFormatString="c"/>
                </mxtl:TreeListColumn.EditorProperties>
            </mxtl:TreeListColumn>
            <mxtl:TreeListColumn Width="*" FieldName="HireDate" BandName="Job"/>
            <mxtl:TreeListColumn Width="*" FieldName="BirthDate" BandName="Personal"/>
            <mxtl:TreeListColumn Width="*" FieldName="Email" BandName="DetailsContact"/>
            <mxtl:TreeListColumn Width="*" FieldName="Phone" BandName="DetailsContact"/>
            <mxtl:TreeListColumn Width="*" FieldName="Address" BandName="DetailsAddress"/>
            <mxtl:TreeListColumn Width="*" FieldName="City" BandName="DetailsAddress"/>
            <mxtl:TreeListColumn Width="*" FieldName="Country" BandName="DetailsAddress"/>
        </mxtl:TreeListControl.Columns>
    </mxtl:TreeListControl>
</mx:MxWindow>
//MainWindow.axaml.cs file
using Avalonia.Controls;
using Eremex.AvaloniaUI.Controls.Common;
using TreeListColumnBands.ViewModels;
namespace TreeListColumnBands.Views;
public partial class MainWindow : MxWindow
{
    public MainWindow()
    {
        this.DataContext = new MainWindowViewModel();
        InitializeComponent();
        employeeTreeList.Loaded += EmployeeTreeList_Loaded;
    }
    private void EmployeeTreeList_Loaded(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
    {
        employeeTreeList.ExpandAllNodes();
    }
}
//MainWindowViewModel.cs file
using System.Collections.Generic;
using System;
using CommunityToolkit.Mvvm.ComponentModel;
using System.Collections.ObjectModel;
namespace TreeListColumnBands.ViewModels;
public partial class MainWindowViewModel : ViewModelBase
{
    public MainWindowViewModel()
    {            
        Employees = EmployeeDataGenerator.GenerateData();
    }
    [ObservableProperty]
    public ObservableCollection<Employee> employees = new();
}
public partial class Employee : ObservableObject
{
    [ObservableProperty]
    public string name;
    [ObservableProperty]
    public string position;
    [ObservableProperty]
    public DateTime birthDate;
    [ObservableProperty]
    public string address;
    [ObservableProperty]
    public string city;
    [ObservableProperty]
    public string country;
    [ObservableProperty]
    public string phone;
    [ObservableProperty]
    public string email;
    [ObservableProperty]
    public DateTime hireDate;
    [ObservableProperty]
    public decimal salary;
    [ObservableProperty]
    public ObservableCollection<Employee> subordinates;
    public Employee(string name, string position, DateTime birthDate,
                   string address, string city, string country,
                   string phone, string email, DateTime hireDate,
                   decimal salary)
    {
        Name = name;
        Position = position;
        BirthDate = birthDate;
        Address = address;
        City = city;
        Country = country;
        Phone = phone;
        Email = email;
        HireDate = hireDate;
        Salary = salary;
        Subordinates = null;
    }
    public void AddSubordinate(Employee subordinate)
    {
        if (Subordinates == null)
            Subordinates = new();
        Subordinates.Add(subordinate);
    }
    public bool HasSubordinates => Subordinates?.Count > 0;
}
public static class EmployeeDataGenerator
{
    public static ObservableCollection<Employee> GenerateData()
    {
        var ceo = new Employee(
            "John Smith", "CEO", new DateTime(1972, 8, 10), "1 Financial District",
            "Riyadh", "Saudi Arabia", "+966 11 123 4567", "j.smith@company.sa", 
            new DateTime(2011, 3, 15), 320000m);
        var vpTech = new Employee(
            "Wei Chen", "VP of Technology", new DateTime(1980, 5, 22), "22 Innovation Park",
            "Shanghai", "China", "+86 21 8765 4321", "w.chen@company.cn", 
            new DateTime(2013, 6, 20), 240000m);
        var devManager = new Employee(
            "Raj Pat", "Development Manager", new DateTime(1985, 11, 30), "33 Tech Corridor",
            "Bangalore", "India", "+91 80 2345 6789", "r.pat@company.in", 
            new DateTime(2016, 4, 10), 160000m);
        var seniorDev = new Employee(
            "Hannah Zhang", "Senior Developer", new DateTime(1990, 3, 12), "44 Code Avenue",
            "Casablanca", "Morocco", "+212 522 987 654", "h.zhang@company.ma", 
            new DateTime(2018, 7, 15), 95000m);
        var juniorDev = new Employee(
            "Lillian Oni", "Junior Developer", new DateTime(1994, 9, 25), "55 Debug Street",
            "Lagos", "Nigeria", "+234 1 345 6789", "l.oni@company.ng", 
            new DateTime(2020, 2, 20), 65000m);
        var cfo = new Employee(
            "Marianne Lockwood", "CFO", new DateTime(1978, 4, 18), "66 Finance Plaza",
            "Ho Chi Minh City", "Vietnam", "+84 28 7654 3210", "m.lock@company.vn", 
            new DateTime(2014, 9, 12), 280000m);
        var financeManager = new Employee(
            "Joanna Bennett", "Finance Manager", new DateTime(1983, 7, 8), "77 Capital Road",
            "Kuala Lumpur", "Malaysia", "+60 3 4567 8901", "j.ben@company.my", 
            new DateTime(2017, 1, 5), 140000m);
        ceo.AddSubordinate(vpTech);
        vpTech.AddSubordinate(devManager);
        devManager.AddSubordinate(seniorDev);
        seniorDev.AddSubordinate(juniorDev);
        ceo.AddSubordinate(cfo); 
        cfo.AddSubordinate(financeManager);
        ObservableCollection<Employee> employees = new ObservableCollection<Employee>();
        employees.Add(ceo);
        return employees;
    }
}
Генерация диапазонов из источника диапазонов¶
Вы можете заполнять диапазоны столбцов из источника диапазонов, определенного в View Model. Используйте свойства TreeListControl.BandsSource и TreeListControl.BandTemplate для генерации диапазонов из коллекции бизнес-объектов.
В качестве альтернативы указанию свойства BandTemplate вы можете использовать свойство Styles для инициализации объектов TreeListBand из бизнес-объектов. См. Инициализация диапазонов с использованием стиля для примера.
Чтобы связать столбцы с диапазонами, установите для каждого столбца свойство TreeListColumn.BandName в соответствие с именем диапазона (TreeListBand.BandName).
Связанный API¶
- TreeListControl.BandsSource— Коллекция бизнес-объектов, используемая для генерации корневых диапазонов.
- TreeListControl.BandTemplate— Шаблон, который создает экземпляры- TreeListBandиз бизнес-объектов.
- TreeListBand.BandsSource— Коллекция бизнес-объектов, используемая для генерации дочерних диапазонов.
- TreeListBand.BandName— Уникальное имя, используемое для идентификации диапазона и связи его со столбцами.
- TreeListColumn.BandName— Имя диапазона, связанного со столбцом. Это значение соответствует значению свойства- TreeListBand.BandName.
Инициализация диапазонов с использованием стиля¶
В качестве альтернативы указанию свойства BandTemplate вы можете использовать свойство Styles для инициализации объектов TreeListBand из бизнес-объектов.
<mxtl:TreeListControl.Styles>
    <Style Selector="mxtl|TreeListBand">
        <Setter Property="BandName" Value="{Binding Name}"/>
        <Setter Property="Header" Value="{Binding DisplayName}"/>
        <Setter Property="HeaderHorizontalAlignment" Value="Center"/>
    </Style>
</mxtl:TreeListControl.Styles>
См. демо "Column Bands" для примера использования свойств BandsSource и Styles.
Генерация диапазонов на основе атрибутов DataAnnotation (для автоматически генерируемых столбцов)¶
Этот подход позволяет использовать атрибуты для связи автоматически генерируемых столбцов с диапазонами.
Когда автоматическое создание столбцов включено (см. TreeListControl.AutoGenerateColumns), контрол TreeList может инициализировать настройки столбцов из специальных атрибутов, примененных к свойствам бизнес-объекта.
Атрибут System.ComponentModel.DataAnnotations.DisplayAttribute позволяет связать автоматически генерируемые столбцы с диапазонами. Укажите параметр DisplayAttribute.GroupName, чтобы определить имя диапазона для соответствующего столбца.
public partial class Order : ObservableObject
{
    [ObservableProperty]
    [property: Display(Order = 0, GroupName = "Order")]
    private int orderId;
    //...
}
Когда TreeList встречает DisplayAttribute.GroupName, он проверяет существование диапазона с соответствующим именем (TreeListBand.BandName). Если такой диапазон не найден, он создается и инициализируется следующим образом:
- Контрол автоматически создает диапазон и устанавливает его свойство TreeListBand.BandNameв значениеDisplayAttribute.GroupName.
- Диапазон добавляется в коллекцию TreeListControl.Bandsконтрола. Вложенные диапазоны добавляются в соответствующие коллекцииTreeListBand.Bands.
- Созданный диапазон связывается с автоматически генерируемым столбцом с использованием свойства TreeListColumn.BandName.
Параметр DisplayAttribute.GroupName поддерживает вложенные диапазоны. Используйте символ '/' для разделения родительских и дочерних диапазонов (например, "ParentBandName/ChildBandName"). Чтобы включить '/' как литеральный символ, используйте нотацию с двойным слэшем ("//").
Замечание
Отдельные имена дочерних диапазонов должны быть уникальными во всем контроле TreeList.
public partial class Order : ObservableObject
{
    [ObservableProperty]
    [property: Display(Order = 20, GroupName = "Shipping Info/Address")]
    private string shipCountry = string.Empty;
    //...
}
Связанный API¶
- 
TreeListControl.AutoGenerateBands(по умолчаниюtrue) — Получает или задает, следует ли автоматически генерировать диапазоны из атрибутовDisplayAttribute.GroupName, примененных к свойствам базового бизнес-объекта. Эти диапазоны затем автоматически связываются с соответствующими автоматически генерируемыми столбцами.Автоматическая генерация диапазонов (и связывание диапазонов с автоматически генерируемыми столбцами) принудительно отключается, если TreeListControl.AutoGenerateColumnsравноfalse.
- 
TreeListControl.BandsиTreeListBand.Bands— Вы можете использовать эти коллекции для доступа к автоматически сгенерированным диапазонам.
Порядок столбцов и диапазонов¶
Контрол TreeListControl упорядочивает столбцы в соответствии с их свойствами TreeListColumn.VisibleIndex.
Порядок заголовков диапазонов определяется визуальным порядком столбцов. Если столбцы, связанные с одним и тем же диапазоном, расположены рядом друг с другом, их заголовки диапазонов объединяются.
<mxtl:TreeListControl.Columns>
    <mxtl:TreeListColumn Width="*" FieldName="FirstName" BandName="Customer"/>
    <mxtl:TreeListColumn Width="*" FieldName="LastName" BandName="Customer"/>
    <mxtl:TreeListColumn Width="*" FieldName="Address" BandName="Details"/>
</mxtl:TreeListControl.Columns>
 
Контрол не переупорядочивает столбцы автоматически, чтобы сгруппировать их по диапазонам. Если столбцы, связанные с одним и тем же диапазоном, расположены в несмежных позициях (разделены столбцами, связанными с другим диапазоном/диапазонами), контрол TreeList создает несколько заголовков диапазонов с одинаковым именем над заголовками столбцов.
В следующем фрагменте кода столбцы, связанные с диапазоном Customer, разделены столбцом Address, который связан с диапазоном Details. Контрол не переупорядочивает столбцы автоматически, чтобы объединить их в один диапазон Customer:
<mxtl:TreeListControl.Columns>
    <mxtl:TreeListColumn Width="*" FieldName="FirstName" BandName="Customer"/>
    <mxtl:TreeListColumn Width="*" FieldName="LastName" BandName="Customer"/>
    <mxtl:TreeListColumn Width="*" FieldName="Address" BandName="Details"/>
    <mxtl:TreeListColumn Width="*" FieldName="Title" BandName="Customer"/>
</mxtl:TreeListControl.Columns>

Операции перетаскивания¶
Перетаскивание столбцов¶
Пользователи могут свободно перетаскивать столбцы внутри контрола, если TreeListControl.AllowColumnMoving равно true (по умолчанию). Если они перетащат столбец в другой диапазон, контрол нарисует соответствующий заголовок диапазона (TreeListColumn.BandHeader) над этим столбцом в его новой позиции. См. Порядок столбцов и диапазонов.
Связанный API¶
- TreeListControl.AllowColumnMoving— Получает или задает, включены ли операции перетаскивания столбцов.
Перетаскивание диапазонов¶
Контрол TreeList не поддерживает операции перетаскивания для диапазонов.
Отображение и скрытие панели диапазонов¶
Панель диапазонов отображает заголовки диапазонов. Панель видима, когда любой столбец связан с существующим диапазоном. Используйте следующее свойство для принудительного скрытия панели диапазонов, когда это требуется:
- TreeListControl.ShowBands— Получает или задает, видима ли панель диапазонов.
Указание содержимого заголовка диапазона¶
- Header— Получает или задает содержимое заголовка диапазона. Если это свойство не задано, диапазон отображает значение свойства- TreeListBand.BandName.
- HeaderTemplate— Получает или задает шаблон, используемый для отображения объекта- Header. Шаблон позволяет отображать изображения и пользовательские контролы, а также выводить текст пользовательским способом.
Пример - Отображение изображения в заголовке диапазона¶
Следующий пример отображает изображение SVG с последующей текстовой подписью в заголовке диапазона. Изображение SVG (файл address-location-icon.svg) находится в папке Assets проекта, а его свойство Build Action установлено в AvaloniaResource.

xmlns:svg="using:Avalonia.Svg.Skia"
<mxtl:TreeListControl.Bands>
    <mxtl:TreeListBand BandName="Customer" HeaderHorizontalAlignment="Center">
        <mxtl:TreeListBand.HeaderTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <svg:Svg Path="/Assets/address-location-icon.svg" Width="16" Height="16" Margin="5" />
                    <TextBlock Text="{Binding}" VerticalAlignment="Center"/>
                </StackPanel>
            </DataTemplate>
        </mxtl:TreeListBand.HeaderTemplate>
    </mxtl:TreeListBand>
</mxtl:TreeListControl.Bands>
Пустой заголовок диапазона¶
Столбцы, не связанные с существующими диапазонами, отображаются под пустым заголовком диапазона.
Разделители диапазонов¶
- TreeListControl.ShowBandSeparators— Включает толстые разделители между смежными диапазонами. Используйте это свойство, чтобы подчеркнуть разделение между диапазонами. Если- ShowBandSeparatorsотключен, tree list рисует обычные разделители столбцов (тонкие линии) между диапазонами.
Скрытие диапазонов¶
Объекты диапазонов не имеют свойства 'Visible'. Чтобы скрыть диапазон, вы должны скрыть столбцы, связанные с этим диапазоном.
Диапазоны без связанных столбцов никогда не отображаются.
Всплывающие подсказки для заголовков диапазонов¶
Используйте свойство HeaderToolTip, чтобы указать пользовательские всплывающие подсказки для заголовков диапазонов. Пользовательские подсказки отображаются при наведении на заголовки диапазонов, независимо от того, обрезан ли текст заголовка диапазона или нет.
<mxtl:TreeListBand BandName="Details" HeaderHorizontalAlignment="Center" HeaderToolTip="Contact and location information">

Когда пользовательская подсказка не назначена диапазону, стандартная подсказка показывается для заголовка диапазона в случае, если текст заголовка обрезан. Стандартная подсказка отображает полный, необрезанный текст заголовка.
* Эта страница была переведена с помощью нейросети Deepseek.
