Группировка в CollectionView

Последнее обновление: 27.01.2023

Элемент CollectionView поддерживает группировку данных. Для этого класс предоставляет ряд свойств:

  • IsGrouped: при значении true будет применяться группировка. Значение по умолчанию - false.

  • GroupHeaderTemplate: шаблон DataTemplate для отображения заголовка группы.

  • GroupFooterTemplate: шаблон DataTemplate для отображения футтера группы.

Рассмотрим, как мы можем сгруппировать элементы в списке.

Допустим, наши данные представлены классом User:

public class Person
{
    public string Name { get; set; } = "";
    public string Company { get; set; } = "";
}

Класс Person определяет два свойства: для имени и для компании пользователя. Так как компания может совпадать у разных пользователей, то можно по этому признаку сгруппировать объекты Person.

Для группировки в начале добавим в проект вспомогательный класс, который назовем Grouping:

using System.Collections.ObjectModel;

namespace HelloApp;

public class Grouping<K, T> : ObservableCollection<T>
{
    public K Name { get; private set; }
    public Grouping(K name, IEnumerable<T> items) : base(items)
    {
         Name = name;
    }
}

Класс Grouping типизирован двумя параметрами. Параметр K представляет тип ключа группы, который будет храниться в свойстве Name. А параметр T представляет тип объектов, которые будут храниться в коллекции Items. Это свойство-коллекция унаследовано от базового класса ObservableCollection. А в конструкторе мы получаем все необходимые данные.

В коде страницы MainPage.xaml.cs создадим список групп:

using System.Collections.ObjectModel;

namespace HelloApp;

public partial class MainPage : ContentPage
{
    // список групп, к которым идет привязка
    public ObservableCollection<Grouping<string, Person>> PeopleGroups { get; set; }
    public MainPage()
	{
		InitializeComponent();

        // начальные данные
        var people = new List<Person>
        {
                new Person {Name="Tom", Company="Microsoft" },
                new Person {Name="Sam", Company="Google" },
                new Person {Name="Alice", Company="Microsoft" },
                new Person {Name="Bob", Company="JetBrains" },
                new Person {Name="Kate", Company="Google" },
        };
        // получаем группы
        var groups = people.GroupBy(p => p.Company).Select(g => new Grouping<string, Person>(g.Key, g));
        // передаем группы в PeopleGroups
        PeopleGroups = new ObservableCollection<Grouping<string, Person>>(groups);
        BindingContext = this;
    }
}

В конструкторе переменная people определяет общие данные, по которым создается коллекция групп в виде свойства PeopleGroups. Группировка в данном случае идет по свойству Company объекта User.

А в коде xaml у MainPage пропишем выражения привязки:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="HelloApp.MainPage" >
    <StackLayout>
        <CollectionView ItemsSource="{Binding PeopleGroups}" IsGrouped="True">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                        <StackLayout Padding="8">
                            <Label Text="{Binding Name}" FontSize="20"  TextColor="#006064"  />
                            <Label Text="{Binding Company}"  />
                    </StackLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </StackLayout>
</ContentPage>

Здесь CollectionView привязан к PeopleGroups, которое содержит группы. Установка свойства IsGrouped="True" добавляет в CollectionView поддержку групп.

И после запуска приложения все данные в списке будут сгруппированы по компаниям:

Группировка в CollectionView в .NET MAUI и C#

Настройка шаблона заголовков группы

По умолчанию заголовки групп не отображаются, поэтому посмотрим, как их настроить. Например, отобразим в качестве заголовка название группы. Для этого изменим разметку xaml:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="HelloApp.MainPage" >
    <StackLayout>
        <CollectionView ItemsSource="{Binding PeopleGroups}" IsGrouped="True">
            <CollectionView.GroupHeaderTemplate>
                <DataTemplate>
                    <Label Text="{Binding Name}" FontSize="22"  TextColor="#006064" />
                </DataTemplate>
            </CollectionView.GroupHeaderTemplate>
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <StackLayout Padding="8">
                        <Label Text="{Binding Name}" FontSize="18"  />
                    </StackLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </StackLayout>
</ContentPage>

Свойство GroupHeaderTemplate получает шаблон DataTemplate, где мы можем настроить отображение. В данном случае заголовок будет представлять элемент Label, который привязан к названию группы:

Настройка заголовоков групп списков в CollectionView в .NET MAUI и C#

Подобным образом можно настроить шаблон для отображения футера с помощью свойства GroupFooterTemplate:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="HelloApp.MainPage"
             xmlns:local="clr-namespace:HelloApp">
    <StackLayout>
        <CollectionView ItemsSource="{Binding PeopleGroups}" IsGrouped="True">
            <CollectionView.GroupHeaderTemplate>
                <DataTemplate>
                    <Label Text="{Binding Name}" FontSize="22"  TextColor="#006064" />
                </DataTemplate>
            </CollectionView.GroupHeaderTemplate>
            <CollectionView.GroupFooterTemplate>
                <DataTemplate>
                    <Label Text="{Binding Count, StringFormat='Total employees: {0:D}'}"
                   Margin="0,0,0,10" />
                </DataTemplate>
            </CollectionView.GroupFooterTemplate>
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <StackLayout Padding="8">
                        <Label Text="{Binding Name}" FontSize="18"  />
                    </StackLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </StackLayout>
</ContentPage>

Футер также представляет метку, текст которой привязан к свойству Count (поскольку коллекция PeopleGroups представляет тип ObservableCollection, то она имеет свойство Count, которое возвращает количество элементов).

Настройка футера групп списков в CollectionView в .NET MAUI и C#
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850