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

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

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

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

using System.Collections.Generic;
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)
        {
            Name = name;
            foreach (T item in items)
                Items.Add(item);
        }
    }
}

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

В качестве объектов возьмем опять же класс Phone:

public class Phone
{
    public string Title { get; set; }
    public string Company { get; set; }
    public int Price { get; set; }
}

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

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Xamarin.Forms;

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

            // начальные данные
            var phones = new List<Phone>
            {
                new Phone {Title="Galaxy S8", Company="Samsung", Price=60000 },
                new Phone {Title="Galaxy S7 Edge", Company="Samsung", Price=50000 },
                new Phone {Title="Huawei P10", Company="Huawei", Price=10000 },
                new Phone {Title="Huawe Mate 8", Company="Huawei", Price=29000 },
                new Phone {Title="Mi6", Company="Xiaomi", Price=55000 },
                new Phone {Title="iPhone 7", Company="Apple", Price=38000 },
                new Phone {Title="iPhone 6S", Company="Apple", Price=50000 }
            };
            // получаем группы
            var groups = phones.GroupBy(p => p.Company).Select(g => new Grouping<string, Phone>(g.Key, g));
            // передаем группы в PhoneGroups
            PhoneGroups = new ObservableCollection<Grouping<string, Phone>>(groups);
            this.BindingContext = this;
        }
    }
}

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

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

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="HelloApp.MainPage">
    <StackLayout>
        <ListView x:Name="phonesList"
              HasUnevenRows="True"
              GroupDisplayBinding="{Binding Name}"
              ItemsSource="{Binding PhoneGroups}"
              IsGroupingEnabled="True">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout>
                            <Label Text="{Binding Title}" />
                            <Label Text="{Binding Price}" />
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>

Привязка ListView здесь идет к свойству PhoneGroups, которое содержит группы. Установка свойства IsGroupingEnabled="True" добавляет в ListView поддержку групп.

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

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

Группировка в ListView в Xamarin Forms

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

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:HelloApp;assembly=HelloApp"
             x:Class="HelloApp.MainPage">
    <StackLayout>
        <ListView x:Name="phonesList"
              HasUnevenRows="True"
              ItemsSource="{Binding PhoneGroups}"
              IsGroupingEnabled="True">
            <ListView.GroupHeaderTemplate>
                <DataTemplate>
                    <ViewCell Height="30">
                        <StackLayout>
                            <Label Text="{Binding Name}" FontSize="Large" />
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.GroupHeaderTemplate>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout>
                            <Label Text="{Binding Title}" />
                            <Label Text="{Binding Price}" />
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>

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

Группировка списков в Xamarin Forms
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850