Поделиться через


Указание макета CollectionView

Просмотрите пример. Обзор примера

Пользовательский интерфейс многоплатформенного приложения .NET (.NET MAUI) CollectionView определяет следующие свойства, которые управляют макетом:

  • ItemsLayoutIItemsLayoutТип , указывает используемый макет.
  • ItemSizingStrategyItemSizingStrategyТип , указывает стратегию измерения элемента, которую следует использовать.

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

По умолчанию CollectionView элемент будет отображаться в вертикальном списке. Однако можно использовать любой из следующих макетов:

  • Вертикальный список — один список столбцов, который увеличивается по вертикали по мере добавления новых элементов.
  • Горизонтальный список — один список строк, который увеличивается горизонтально по мере добавления новых элементов.
  • Вертикальная сетка — сетка с несколькими столбцами, которая растет вертикально по мере добавления новых элементов.
  • Горизонтальная сетка — сетка с несколькими строками, которая растет горизонтально по мере добавления новых элементов.

Эти макеты можно указать, задав свойству ItemsLayout класс, производный ItemsLayout от класса. Этот класс определяет приведенные ниже свойства.

  • OrientationItemsLayoutOrientationТип , указывает направление, в котором CollectionView добавляются элементы.
  • SnapPointsAlignmentТип , указывает, как точки привязки SnapPointsAlignmentвыравниваются с элементами.
  • SnapPointsTypeSnapPointsTypeТип , указывает поведение точек оснастки при прокрутке.

Эти свойства поддерживаются BindableProperty объектами, что означает, что свойства могут быть целевыми объектами привязки данных. Дополнительные сведения о точках оснастки см. в разделе "Точки оснастки" в элементе управления прокруткой в CollectionView.

Перечисление ItemsLayoutOrientation определяет следующие члены:

  • Vertical указывает, что CollectionView будет развернуто по вертикали по мере добавления элементов.
  • Horizontal указывает, что CollectionView будет развернуто горизонтально по мере добавления элементов.

Класс LinearItemsLayout наследует ItemSpacing от ItemsLayout класса и определяет свойство типаdouble, представляющее пустое пространство вокруг каждого элемента. Значение по умолчанию этого свойства равно 0, а его значение всегда должно быть больше или равно 0. Класс LinearItemsLayout также определяет статические Vertical и Horizontal члены. Эти элементы можно использовать для создания вертикальных или горизонтальных списков соответственно. Кроме того, LinearItemsLayout можно создать объект, указав ItemsLayoutOrientation элемент перечисления в качестве аргумента.

Класс GridItemsLayout наследует от ItemsLayout класса и определяет следующие свойства:

  • VerticalItemSpacingdoubleТип , представляющий вертикальное пустое пространство вокруг каждого элемента. Значение по умолчанию этого свойства равно 0, а его значение всегда должно быть больше или равно 0.
  • HorizontalItemSpacingdoubleТип , представляющий горизонтальное пустое пространство вокруг каждого элемента. Значение по умолчанию этого свойства равно 0, а его значение всегда должно быть больше или равно 0.
  • SpanintТип , представляющий количество столбцов или строк, отображаемых в сетке. Значение по умолчанию этого свойства равно 1, а его значение всегда должно быть больше или равно 1.

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

Примечание.

CollectionView использует собственные подсистемы макета для выполнения макета.

Вертикальный список

По умолчанию CollectionView будут отображаться его элементы в вертикальном макете списка. Поэтому не обязательно задать ItemsLayout свойство для использования этого макета:

<CollectionView ItemsSource="{Binding Monkeys}">
    <CollectionView.ItemTemplate>
        <DataTemplate>
            <Grid Padding="10">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
                <Image Grid.RowSpan="2"
                       Source="{Binding ImageUrl}"
                       Aspect="AspectFill"
                       HeightRequest="60"
                       WidthRequest="60" />
                <Label Grid.Column="1"
                       Text="{Binding Name}"
                       FontAttributes="Bold" />
                <Label Grid.Row="1"
                       Grid.Column="1"
                       Text="{Binding Location}"
                       FontAttributes="Italic"
                       VerticalOptions="End" />
            </Grid>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

Однако для полноты в XAML CollectionView можно задать для отображения его элементов в вертикальном списке, задав для свойства значение ItemsLayout VerticalList:

<CollectionView ItemsSource="{Binding Monkeys}"
                ItemsLayout="VerticalList">
    ...
</CollectionView>

Кроме того, это можно сделать, задав ItemsLayout ItemsLayoutOrientation Vertical свойство LinearItemsLayout объекту, указав элемент перечисления в качестве Orientation значения свойства:

<CollectionView ItemsSource="{Binding Monkeys}">
    <CollectionView.ItemsLayout>
        <LinearItemsLayout Orientation="Vertical" />
    </CollectionView.ItemsLayout>
    ...
</CollectionView>

Эквивалентный код на C# выглядит так:

CollectionView collectionView = new CollectionView
{
    ...
    ItemsLayout = LinearItemsLayout.Vertical
};

Это приводит к созданию одного списка столбцов, который увеличивается по вертикали по мере добавления новых элементов:

Снимок экрана: макет вертикального списка CollectionView.

Совет

CollectionView Размещение внутри VerticalStackLayout может остановить прокрутку CollectionView и может ограничить количество отображаемых элементов. В этой ситуации замените VerticalStackLayout элементом Grid.

Горизонтальный список

В XAML его элементы могут отображаться в горизонтальном списке, CollectionView задав для свойства значение ItemsLayout HorizontalList:

<CollectionView ItemsSource="{Binding Monkeys}"
                ItemsLayout="HorizontalList">
    <CollectionView.ItemTemplate>
        <DataTemplate>
            <Grid Padding="10">
                <Grid.RowDefinitions>
                    <RowDefinition Height="35" />
                    <RowDefinition Height="35" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="70" />
                    <ColumnDefinition Width="140" />
                </Grid.ColumnDefinitions>
                <Image Grid.RowSpan="2"
                       Source="{Binding ImageUrl}"
                       Aspect="AspectFill"
                       HeightRequest="60"
                       WidthRequest="60" />
                <Label Grid.Column="1"
                       Text="{Binding Name}"
                       FontAttributes="Bold"
                       LineBreakMode="TailTruncation" />
                <Label Grid.Row="1"
                       Grid.Column="1"
                       Text="{Binding Location}"
                       LineBreakMode="TailTruncation"
                       FontAttributes="Italic"
                       VerticalOptions="End" />
            </Grid>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

Кроме того, этот макет можно выполнить, задав ItemsLayout ItemsLayoutOrientation Horizontal свойство LinearItemsLayout объекту, указав элемент перечисления в качестве Orientation значения свойства:

<CollectionView ItemsSource="{Binding Monkeys}">
    <CollectionView.ItemsLayout>
        <LinearItemsLayout Orientation="Horizontal" />
    </CollectionView.ItemsLayout>
    ...
</CollectionView>

Эквивалентный код на C# выглядит так:

CollectionView collectionView = new CollectionView
{
    ...
    ItemsLayout = LinearItemsLayout.Horizontal
};

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

Снимок экрана: макет горизонтального списка CollectionView.

Вертикальная сетка

В XAML элементы могут отображаться в вертикальной сетке, CollectionView задав для свойства значение ItemsLayout VerticalGrid:

<CollectionView ItemsSource="{Binding Monkeys}"
                ItemsLayout="VerticalGrid, 2">
    <CollectionView.ItemTemplate>
        <DataTemplate>
            <Grid Padding="10">
                <Grid.RowDefinitions>
                    <RowDefinition Height="35" />
                    <RowDefinition Height="35" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="70" />
                    <ColumnDefinition Width="80" />
                </Grid.ColumnDefinitions>
                <Image Grid.RowSpan="2"
                       Source="{Binding ImageUrl}"
                       Aspect="AspectFill"
                       HeightRequest="60"
                       WidthRequest="60" />
                <Label Grid.Column="1"
                       Text="{Binding Name}"
                       FontAttributes="Bold"
                       LineBreakMode="TailTruncation" />
                <Label Grid.Row="1"
                       Grid.Column="1"
                       Text="{Binding Location}"
                       LineBreakMode="TailTruncation"
                       FontAttributes="Italic"
                       VerticalOptions="End" />
            </Grid>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

Кроме того, этот макет можно выполнить, задав свойство GridItemsLayout объектуItemsLayout, свойству которого Orientation присвоено Verticalзначение :

<CollectionView ItemsSource="{Binding Monkeys}">
    <CollectionView.ItemsLayout>
       <GridItemsLayout Orientation="Vertical"
                        Span="2" />
    </CollectionView.ItemsLayout>
    ...
</CollectionView>

Эквивалентный код на C# выглядит так:

CollectionView collectionView = new CollectionView
{
    ...
    ItemsLayout = new GridItemsLayout(2, ItemsLayoutOrientation.Vertical)
};

По умолчанию вертикали GridItemsLayout будут отображать элементы в одном столбце. Однако в этом примере свойство имеет GridItemsLayout.Span значение 2. Это приводит к созданию сетки с двумя столбцами по вертикали по мере добавления новых элементов:

Снимок экрана: макет вертикальной сетки CollectionView.

Горизонтальная сетка

В XAML элемент может отображать свои элементы в горизонтальной сетке, CollectionView задав для свойства значение ItemsLayout HorizontalGrid:

<CollectionView ItemsSource="{Binding Monkeys}"
                ItemsLayout="HorizontalGrid, 4">
    <CollectionView.ItemTemplate>
        <DataTemplate>
            <Grid Padding="10">
                <Grid.RowDefinitions>
                    <RowDefinition Height="35" />
                    <RowDefinition Height="35" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="70" />
                    <ColumnDefinition Width="140" />
                </Grid.ColumnDefinitions>
                <Image Grid.RowSpan="2"
                       Source="{Binding ImageUrl}"
                       Aspect="AspectFill"
                       HeightRequest="60"
                       WidthRequest="60" />
                <Label Grid.Column="1"
                       Text="{Binding Name}"
                       FontAttributes="Bold"
                       LineBreakMode="TailTruncation" />
                <Label Grid.Row="1"
                       Grid.Column="1"
                       Text="{Binding Location}"
                       LineBreakMode="TailTruncation"
                       FontAttributes="Italic"
                       VerticalOptions="End" />
            </Grid>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

Кроме того, этот макет можно выполнить, задав свойство GridItemsLayout объектуItemsLayout, свойству которого Orientation присвоено Horizontalзначение :

<CollectionView ItemsSource="{Binding Monkeys}">
    <CollectionView.ItemsLayout>
       <GridItemsLayout Orientation="Horizontal"
                        Span="4" />
    </CollectionView.ItemsLayout>
    ...
</CollectionView>

Эквивалентный код на C# выглядит так:

CollectionView collectionView = new CollectionView
{
    ...
    ItemsLayout = new GridItemsLayout(4, ItemsLayoutOrientation.Horizontal)
};

По умолчанию горизонтальное GridItemsLayout отображение элементов в одной строке. Однако в этом примере свойство имеет GridItemsLayout.Span значение 4. Это приводит к тому, что сетка с четырьмя строками растет горизонтально по мере добавления новых элементов:

Снимок экрана: макет горизонтальной сетки CollectionView.

Колонтитулы

CollectionView может представлять верхний и нижний колонтитул, прокручиваемый элементами в списке. Верхний и нижний колонтитул могут быть строками, представлениями или DataTemplate объектами.

CollectionView определяет следующие свойства для указания верхнего и нижнего колонтитула:

  • HeaderobjectТип , указывает строку, привязку или представление, которое будет отображаться в начале списка.
  • HeaderTemplate, тип DataTemplate, указывает DataTemplate , что используется для форматирования Header.
  • FooterobjectТип , указывает строку, привязку или представление, которое будет отображаться в конце списка.
  • FooterTemplate, тип DataTemplate, указывает DataTemplate , что используется для форматирования Footer.

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

При добавлении заголовка в макет, который растет по горизонтали, слева направо, заголовок отображается слева от списка. Аналогичным образом, когда нижний колонтитул добавляется в макет, который растет горизонтально слева направо, нижний колонтитул отображается справа от списка.

Значения Header и Footer свойства можно задать string , как показано в следующем примере:

<CollectionView ItemsSource="{Binding Monkeys}"
                Header="Monkeys"
                Footer="2019">
    ...
</CollectionView>

Эквивалентный код на C# выглядит так:

CollectionView collectionView = new CollectionView
{
    Header = "Monkeys",
    Footer = "2019"
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");

Этот код приводит к следующим снимкам экрана: заголовок, показанный на снимке экрана iOS, и нижний колонтитул, показанный на снимке экрана Android:

Снимок экрана: строка CollectionView и нижний колонтитул.

Для Header каждого Footer свойства можно задать представление. Это может быть одно представление или представление, содержащее несколько дочерних представлений. В следующем примере показаны Header свойства каждого Footer набора StackLayout для объекта, содержащего Label объект:

<CollectionView ItemsSource="{Binding Monkeys}">
    <CollectionView.Header>
        <StackLayout BackgroundColor="LightGray">
            <Label Margin="10,0,0,0"
                   Text="Monkeys"
                   FontSize="12"
                   FontAttributes="Bold" />
        </StackLayout>
    </CollectionView.Header>
    <CollectionView.Footer>
        <StackLayout BackgroundColor="LightGray">
            <Label Margin="10,0,0,0"
                   Text="Friends of Xamarin Monkey"
                   FontSize="12"
                   FontAttributes="Bold" />
        </StackLayout>
    </CollectionView.Footer>
    ...
</CollectionView>

Эквивалентный код на C# выглядит так:

StackLayout headerStackLayout = new StackLayout();
header.StackLayout.Add(new Label { Text = "Monkeys", ... } );
StackLayout footerStackLayout = new StackLayout();
footerStackLayout.Add(new Label { Text = "Friends of Xamarin Monkey", ... } );

CollectionView collectionView = new CollectionView
{  
    Header = headerStackLayout,
    Footer = footerStackLayout            
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");

Этот код приводит к следующим снимкам экрана: заголовок, показанный на снимке экрана iOS, и нижний колонтитул, показанный на снимке экрана Android:

Снимок экрана: верхний и нижний колонтитул CollectionView с помощью представлений.

FooterTemplate Свойства HeaderTemplate можно задать для DataTemplate объектов, которые используются для форматирования верхнего и нижнего колонтитулов. В этом сценарии Header Footer свойства должны привязаться к текущему источнику для применения шаблонов, как показано в следующем примере:

<CollectionView ItemsSource="{Binding Monkeys}"
                Header="{Binding .}"
                Footer="{Binding .}">
    <CollectionView.HeaderTemplate>
        <DataTemplate>
            <StackLayout BackgroundColor="LightGray">
                <Label Margin="10,0,0,0"
                       Text="Monkeys"
                       FontSize="12"
                       FontAttributes="Bold" />
            </StackLayout>
        </DataTemplate>
    </CollectionView.HeaderTemplate>
    <CollectionView.FooterTemplate>
        <DataTemplate>
            <StackLayout BackgroundColor="LightGray">
                <Label Margin="10,0,0,0"
                       Text="Friends of Xamarin Monkey"
                       FontSize="12"
                       FontAttributes="Bold" />
            </StackLayout>
        </DataTemplate>
    </CollectionView.FooterTemplate>
    ...
</CollectionView>

Эквивалентный код на C# выглядит так:

CollectionView collectionView = new CollectionView
{
    HeaderTemplate = new DataTemplate(() =>
    {
        return new StackLayout { };
    }),
    FooterTemplate = new DataTemplate(() =>
    {
        return new StackLayout { };
    })
};
collectionView.SetBinding(ItemsView.HeaderProperty, ".");
collectionView.SetBinding(ItemsView.FooterProperty, ".");
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");

Этот код приводит к следующим снимкам экрана: заголовок, показанный на снимке экрана iOS, и нижний колонтитул, показанный на снимке экрана Android:

Снимок экрана: верхний и нижний колонтитул CollectionView с помощью шаблонов.

Интервалы элементов

По умолчанию между каждым элементом в элементе CollectionViewнет места. Это поведение можно изменить, задав свойства в макете элементов, используемом этим элементом CollectionView.

CollectionView Если свойство присваивается ItemsLayout LinearItemsLayout объекту, LinearItemsLayout.ItemSpacing это свойство можно задать значениеdouble, представляющее пространство между элементами:

<CollectionView ItemsSource="{Binding Monkeys}">
    <CollectionView.ItemsLayout>
        <LinearItemsLayout Orientation="Vertical"
                           ItemSpacing="20" />
    </CollectionView.ItemsLayout>
    ...
</CollectionView>

Примечание.

Свойство LinearItemsLayout.ItemSpacing имеет набор обратного вызова проверки, который гарантирует, что значение свойства всегда больше или равно 0.

Эквивалентный код на C# выглядит так:

CollectionView collectionView = new CollectionView
{
    ...
    ItemsLayout = new LinearItemsLayout(ItemsLayoutOrientation.Vertical)
    {
        ItemSpacing = 20
    }
};

Этот код приводит к вертикальному списку столбцов с интервалом от 20 между элементами:

Снимок экрана: CollectionView с интервалами элементов.

CollectionView Если свойство GridItemsLayout ItemsLayout присваивается объекту, значения и GridItemsLayout.HorizontalItemSpacing свойства можно задать для double значений, GridItemsLayout.VerticalItemSpacing представляющих пустое пространство по вертикали и горизонтально между элементами:

<CollectionView ItemsSource="{Binding Monkeys}">
    <CollectionView.ItemsLayout>
       <GridItemsLayout Orientation="Vertical"
                        Span="2"
                        VerticalItemSpacing="20"
                        HorizontalItemSpacing="30" />
    </CollectionView.ItemsLayout>
    ...
</CollectionView>

Примечание.

GridItemsLayout.HorizontalItemSpacing Свойства GridItemsLayout.VerticalItemSpacing имеют набор обратных вызовов проверки, что гарантирует, что значения свойств всегда больше или равно 0.

Эквивалентный код на C# выглядит так:

CollectionView collectionView = new CollectionView
{
    ...
    ItemsLayout = new GridItemsLayout(2, ItemsLayoutOrientation.Vertical)
    {
        VerticalItemSpacing = 20,
        HorizontalItemSpacing = 30
    }
};

Этот код приводит к вертикальной двухколоночной сетке с вертикальным интервалом между элементами и горизонтальным интервалом от 30 между элементами:

Снимок экрана: КоллекцияView с интервалами элементов сетки.

Размер элемента

По умолчанию каждый элемент в объекте CollectionView измеряется по отдельности и размер, при условии, что элементы пользовательского интерфейса в элементе DataTemplate не указывают фиксированные размеры. Это поведение, которое может быть изменено, определяется значением CollectionView.ItemSizingStrategy свойства. Это значение свойства можно задать одному из ItemSizingStrategy элементов перечисления:

  • MeasureAllItems — каждый элемент измеряется по отдельности. Это значение по умолчанию.
  • MeasureFirstItem — измеряется только первый элемент, причем все последующие элементы получают тот же размер, что и первый элемент.

Внимание

Стратегия MeasureFirstItem изменения размера приведет к увеличению производительности при использовании в ситуациях, когда размер элемента предназначен для единообразия во всех элементах.

В следующем примере кода показано задание ItemSizingStrategy свойства:

<CollectionView ...
                ItemSizingStrategy="MeasureFirstItem">
    ...
</CollectionView>

Эквивалентный код на C# выглядит так:

CollectionView collectionView = new CollectionView
{
    ...
    ItemSizingStrategy = ItemSizingStrategy.MeasureFirstItem
};

Динамическое изменение размера элементов

Элементы в объекте CollectionView могут динамически изменяться во время выполнения путем изменения связанных с макетом свойств элементов в пределах среды DataTemplateвыполнения. Например, следующий пример кода изменяет HeightRequest и WidthRequest свойства Image объекта:

void OnImageTapped(object sender, EventArgs e)
{
    Image image = sender as Image;
    image.HeightRequest = image.WidthRequest = image.HeightRequest.Equals(60) ? 100 : 60;
}

Обработчик OnImageTapped событий выполняется в ответ на Image касания объекта и изменяет размеры изображения таким образом, чтобы его было проще просматривать:

Снимок экрана: КоллекцияView с динамическим изменением размера элементов.

Макет справа налево

CollectionView может макетировать содержимое в направлении потока справа налево, задав для свойства значение FlowDirection RightToLeft. FlowDirection Однако свойство в идеале должно быть задано на странице или корневом макете, что приводит ко всем элементам страницы или корневому макету для реагирования на направление потока:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="CollectionViewDemos.Views.VerticalListFlowDirectionPage"
             Title="Vertical list (RTL FlowDirection)"
             FlowDirection="RightToLeft">
    <Grid Margin="20">
        <CollectionView ItemsSource="{Binding Monkeys}">
            ...
        </CollectionView>
    </Grid>
</ContentPage>

Значение по умолчанию FlowDirection для элемента с родительским MatchParentэлементом . Поэтому значение CollectionView свойства наследуется FlowDirection от Gridзначения, которое, в свою очередь, наследует FlowDirection значение свойства от ContentPage. Это приводит к отображению макета справа налево на следующем снимке экрана:

Снимок экрана: макет вертикального списка CollectionView справа налево.

Дополнительные сведения о направлении потока см. в разделе "Справа налево".