CollectionView 定义以下对布局进行控制的属性:
ItemsLayout,类型为IItemsLayout,指定要使用的布局。ItemSizingStrategy,类型为ItemSizingStrategy,指定要使用的项度量策略。
这些属性由 BindableProperty 对象提供支持,这意味着它们可以作为数据绑定的目标。
默认情况下,CollectionView 将在垂直列表中显示其项。 但是,可以使用以下任一布局:
- 垂直列表 – 随着添加新项而在垂直方向上增加的单列列表。
- 水平列表 – 随着添加新项而在水平方向增加的单行列表。
- 垂直网格 – 随着添加新项而在垂直方向上增加的多列网格。
- 水平网格 – 随着添加新项而在水平方向增加的多行网格。
可以通过将 ItemsLayout 属性设置为派生自 ItemsLayout 类的类来指定这些布局。 此类定义了以下属性:
Orientation,类型为ItemsLayoutOrientation,指定在添加项时CollectionView展开的方向。SnapPointsAlignment,类型为SnapPointsAlignment,指定捕捉点与项的对齐方式。SnapPointsType,类型为SnapPointsType,指定滚动时捕捉点的行为。
这些属性由 BindableProperty 对象提供支持,这意味着这些属性可以作为数据绑定的目标。 有关对齐点的详细信息,请参阅 Xamarin.Forms CollectionView 滚动指南中的对齐点。
ItemsLayoutOrientation 枚举定义以下成员:
Vertical指示CollectionView在添加项时垂直扩展。Horizontal指示CollectionView在添加项时水平扩展。
LinearItemsLayout 类继承自 ItemsLayout 类,并定义类型为 double 的 ItemSpacing 属性,该属性表示每个项周围的空白空间。 此属性的默认值为 0,其值必须始终大于或等于 0。 LinearItemsLayout 类还定义静态 Vertical 和 Horizontal 成员。 这些成员可用于分别创建垂直列表或水平列表。 或者,可以创建 LinearItemsLayout 对象,将 ItemsLayoutOrientation 枚举成员指定为参数。
GridItemsLayout 类继承自 ItemsLayout 类,并定义以下属性:
VerticalItemSpacing,类型为double,表示每个项周围的垂直空白空间。 此属性的默认值为 0,并且其值必须始终大于或等于 0。HorizontalItemSpacing,类型为double,表示每个项周围的水平空白空间。 此属性的默认值为 0,并且其值必须始终大于或等于 0。Span,类型为int,表示要在网格中显示的列数或行数。 此属性的默认值为 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 属性设置为 LinearItemsLayout 对象,并将 Vertical ItemsLayoutOrientation 枚举成员指定为 Orientation 属性值,来实现此布局:
<CollectionView ItemsSource="{Binding Monkeys}">
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Vertical" />
</CollectionView.ItemsLayout>
...
</CollectionView>
等效 C# 代码如下:
CollectionView collectionView = new CollectionView
{
...
ItemsLayout = LinearItemsLayout.Vertical
};
这会生成单列列表,该列表会随着添加新项在垂直方向上增加:
水平列表
在 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 属性设置为 LinearItemsLayout 对象,并将 Horizontal ItemsLayoutOrientation 枚举成员指定为 Orientation 属性值,来实现此布局:
<CollectionView ItemsSource="{Binding Monkeys}">
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Horizontal" />
</CollectionView.ItemsLayout>
...
</CollectionView>
等效 C# 代码如下:
CollectionView collectionView = new CollectionView
{
...
ItemsLayout = LinearItemsLayout.Horizontal
};
这会生成单行列表,该列表会随着添加新项而在水平方向增加:
垂直网格
在 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>
或者,也可以通过将 ItemsLayout 属性设置为 GridItemsLayout 对象,将该对象的 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。 这将生成一个两列网格,该网格会随着添加新项而在垂直方向上增加:
水平网格
在 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>
或者,也可以通过将 ItemsLayout 属性设置为 GridItemsLayout 对象,将该对象的 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 可以显示随列表中的项一起滚动的页眉和页脚。 页眉和页脚可以是字符串、视图或 DataTemplate 对象。
CollectionView 定义用于指定页眉和页脚的以下属性:
object类型的Header指定将在列表开头显示的字符串、绑定或视图。DataTemplate类型的HeaderTemplate指定用于设置Header格式的DataTemplate。object类型的Footer指定将在列表末尾显示的字符串、绑定或视图。DataTemplate类型的FooterTemplate指定用于设置Footer格式的DataTemplate。
这些属性由 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 屏幕截图中:
在页眉和页脚中显示视图
可以将 Footer 和 Header 属性都设置为视图。 这可以是单个视图,也可以是包含多个子视图的视图。 以下示例显示 Header 和 Footer 属性,每个属性都设置为包含 Label 对象的 StackLayout 对象:
<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 屏幕截图中:
显示模板化页眉和页脚
可以将 HeaderTemplate 和 FooterTemplate 属性设置为用于设置页眉和页脚格式的 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="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 屏幕截图中:
项间距
默认情况下,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 将其 ItemsLayout 属性设置为 GridItemsLayout 对象时,可以将 GridItemsLayout.VerticalItemSpacing 和 GridItemsLayout.HorizontalItemSpacing 属性设置为 double 值,这些值表示项之间的垂直和水平空白区域:
<CollectionView ItemsSource="{Binding Monkeys}">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical"
Span="2"
VerticalItemSpacing="20"
HorizontalItemSpacing="30" />
</CollectionView.ItemsLayout>
...
</CollectionView>
注意
GridItemsLayout.VerticalItemSpacing 和 GridItemsLayout.HorizontalItemSpacing 属性设置了验证回调,这可确保属性的值始终大于或等于 0。
等效 C# 代码如下:
CollectionView collectionView = new CollectionView
{
...
ItemsLayout = new GridItemsLayout(2, ItemsLayoutOrientation.Vertical)
{
VerticalItemSpacing = 20,
HorizontalItemSpacing = 30
}
};
此代码生成一个垂直两列网格,各个项之间的垂直间距为 20,各个项之间水平间距为 30:
调整项大小
默认情况下,如果 DataTemplate 中的 UI 元素未指定固定大小,则单独测量和调整 CollectionView 中每个项的大小。 此行为(可以更改)由 CollectionView.ItemSizingStrategy 属性值指定。 可将此属性值设置为 ItemSizingStrategy 枚举成员中的一个:
MeasureAllItems– 每个项都是单独测量的。 这是默认值。MeasureFirstItem– 仅测量第一项,所有后续项的大小都与第一项相同。
重要
在所有项的大小均一致的情况下使用 MeasureFirstItem 大小调整策略将可以提高性能。
以下代码示例展示如何设置 ItemSizingStrategy 属性:
<CollectionView ...
ItemSizingStrategy="MeasureFirstItem">
...
</CollectionView>
等效 C# 代码如下:
CollectionView collectionView = new CollectionView
{
...
ItemSizingStrategy = ItemSizingStrategy.MeasureFirstItem
};
动态调整项大小
在运行时可以通过更改 DataTemplate 中元素的布局相关属性,动态调整 CollectionView 中项的大小。 例如,以下代码示例更改 Image 对象的 HeightRequest 和 WidthRequest 属性:
void OnImageTapped(object sender, EventArgs e)
{
Image image = sender as Image;
image.HeightRequest = image.WidthRequest = image.HeightRequest.Equals(60) ? 100 : 60;
}
执行 OnImageTapped 事件处理程序以响应正在点击的 Image 对象,并更改图像尺寸,以便其更易于查看:
从右到左的布局
CollectionView 可按从右到左的流方向布局其内容,方法是将其 FlowDirection 属性设置为 RightToLeft。 但是,最好在页面或根布局上设置 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 从 StackLayout 继承 FlowDirection 属性值,而前者又从 ContentPage 继承 FlowDirection 属性值。 这会生成如以下屏幕截图所示的布局:
有关流方向的详细信息,请参阅从右到左本地化。










