Xamarin.Forms Макет CollectionView

Download Sample Скачайте пример

CollectionView определяет следующие свойства, которые управляют макетом:

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

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

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

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

Эти свойства поддерживаются BindableProperty объектами, что означает, что свойства могут быть целевыми объектами привязки данных. Дополнительные сведения о точках привязки см. в руководстве по прокруткеXamarin.Forms 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 можно задать для отображения его элементов в вертикальном списке, задав для свойства значение ItemsLayoutVerticalList:

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

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

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

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

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

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

Screenshot of a CollectionView vertical list layout, on iOS and Android

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

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

<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>

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

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

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

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

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

Screenshot of a CollectionView horizontal list layout, on iOS and Android

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

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

<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. Это приводит к созданию сетки с двумя столбцами по вертикали по мере добавления новых элементов:

Screenshot of a CollectionView vertical grid layout, on iOS and Android

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

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

<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. Это приводит к тому, что сетка с четырьмя строками растет горизонтально по мере добавления новых элементов:

Screenshot of a CollectionView horizontal grid layout, on iOS and Android

Колонтитулы

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:

Screenshot of a CollectionView string header and footer, on iOS and Android

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

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

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

CollectionView collectionView = new CollectionView
{
    Header = new StackLayout
    {
        Children =
        {
            new Label { Text = "Monkeys", ... }
        }
    },
    Footer = new StackLayout
    {
        Children =
        {
            new Label { Text = "Friends of Xamarin Monkey", ... }
        }
    }
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");

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

Screenshot of a CollectionView header and footer using views, on iOS and Android

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

<CollectionView ItemsSource="{Binding Monkeys}"
                Header="{Binding .}"
                Footer="{Binding .}">
    <CollectionView.HeaderTemplate>
        <DataTemplate>
            <StackLayout BackgroundColor="LightGray">
                <Label Margin="10,0,0,0"
                       Text="Monkeys"
                       FontSize="Small"
                       FontAttributes="Bold" />
            </StackLayout>
        </DataTemplate>
    </CollectionView.HeaderTemplate>
    <CollectionView.FooterTemplate>
        <DataTemplate>
            <StackLayout BackgroundColor="LightGray">
                <Label Margin="10,0,0,0"
                       Text="Friends of Xamarin Monkey"
                       FontSize="Small"
                       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:

Screenshot of a CollectionView header and footer using templates, on iOS and Android

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

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

CollectionView Если свойство присваивается ItemsLayoutLinearItemsLayout объекту, 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 между элементами:

Screenshot of a CollectionView with item spacing, on iOS and Android

CollectionView Если свойство GridItemsLayoutItemsLayout присваивается объекту, значения и 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
    }
};

Этот код приводит к вертикальной сетке с двумя столбцами, которая имеет вертикальный интервал между элементами 20 и горизонтальный интервал от 30 между элементами:

Screenshot of a CollectionView with item spacing, on Android

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

По умолчанию каждый элемент в объекте 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 касания объекта и изменяет размеры изображения таким образом, чтобы его было проще просматривать:

Screenshot of a CollectionView with dynamic item sizing, on iOS and Android

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

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

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

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

Screenshot of a CollectionView right-to-left vertical list layout, on iOS and Android

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