除了自定义列表中每行的 ViewCell 实例之外,Xamarin.FormsListView 还允许你自定义列表的呈现方式。
分组
以连续滚动列表形式呈现时,大量数据可能会变得难以处理。 在这些情况下,启用分组可以通过更好地组织内容和激活特定于平台的控件来使数据导航变得更加容易,从而改善用户体验。
为 ListView 激活分组时,将为每个组添加一个标题行。
若要启用分组功能,请执行以下操作:
- 创建列表列表(组列表,每个组都是元素列表)。
- 将 ListView的ItemsSource设置为该列表。
- 将 IsGroupingEnabled设置为 true。
- 将 GroupDisplayBinding设置为绑定到用作组标题的组属性。
- [可选] 将 GroupShortNameBinding设置为绑定到用作组的短名称的组属性。 短名称用于跳转列表(iOS 上的右侧列)。
首先为组创建类:
public class PageTypeGroup : List<PageModel>
    {
        public string Title { get; set; }
        public string ShortName { get; set; } //will be used for jump lists
        public string Subtitle { get; set; }
        private PageTypeGroup(string title, string shortName)
        {
            Title = title;
            ShortName = shortName;
        }
        public static IList<PageTypeGroup> All { private set; get; }
    }
在上面的代码中,All 是将作为绑定源提供给 ListView 的列表。 Title 和 ShortName 是将用于组标题的属性。
在此阶段,All 是一个空列表。 添加静态构造函数,以便在程序启动时填充列表:
static PageTypeGroup()
{
    List<PageTypeGroup> Groups = new List<PageTypeGroup> {
            new PageTypeGroup ("Alpha", "A"){
                new PageModel("Amelia", "Cedar", new switchCellPage(),""),
                new PageModel("Alfie", "Spruce", new switchCellPage(), "grapefruit.jpg"),
                new PageModel("Ava", "Pine", new switchCellPage(), "grapefruit.jpg"),
                new PageModel("Archie", "Maple", new switchCellPage(), "grapefruit.jpg")
            },
            new PageTypeGroup ("Bravo", "B"){
                new PageModel("Brooke", "Lumia", new switchCellPage(),""),
                new PageModel("Bobby", "Xperia", new switchCellPage(), "grapefruit.jpg"),
                new PageModel("Bella", "Desire", new switchCellPage(), "grapefruit.jpg"),
                new PageModel("Ben", "Chocolate", new switchCellPage(), "grapefruit.jpg")
            }
        };
        All = Groups; //set the publicly accessible list
}
在上面的代码中,我们还可以对 Groups 的元素调用 Add,这些元素是类型 PageTypeGroup 的实例。 此方法之所以可行,是因为 PageTypeGroup 继承自 List<PageModel>。
下面是用于显示已分组列表的 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"
             x:Class="DemoListView.GroupingViewPage"
    <ContentPage.Content>
        <ListView  x:Name="GroupedView"
                   GroupDisplayBinding="{Binding Title}"
                   GroupShortNameBinding="{Binding ShortName}"
                   IsGroupingEnabled="true">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextCell Text="{Binding Title}"
                              Detail="{Binding Subtitle}" />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </ContentPage.Content>
</ContentPage>
该 XAML 执行下列操作:
- 将 GroupShortNameBinding设置为我们的组类中定义的ShortName属性
- 将 GroupDisplayBinding设置为我们的组类中定义的Title属性
- 将 IsGroupingEnabled设置为 true
- 将 ListView的ItemsSource更改为已分组列表
以下屏幕截图显示生成的 UI:

自定义分组
如果列表中已启用分组,则还可以自定义组标头。
与 ListView 有一个用于定义行显示方式的 ItemTemplate 类似,ListView 有一个 GroupHeaderTemplate。
此处显示了在 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"
             x:Class="DemoListView.GroupingViewPage">
    <ContentPage.Content>
        <ListView x:Name="GroupedView"
                  GroupDisplayBinding="{Binding Title}"
                  GroupShortNameBinding="{Binding ShortName}"
                  IsGroupingEnabled="true">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextCell Text="{Binding Title}"
                              Detail="{Binding Subtitle}"
                              TextColor="#f35e20"
                              DetailColor="#503026" />
                </DataTemplate>
            </ListView.ItemTemplate>
            <!-- Group Header Customization-->
            <ListView.GroupHeaderTemplate>
                <DataTemplate>
                    <TextCell Text="{Binding Title}"
                              Detail="{Binding ShortName}"
                              TextColor="#f35e20"
                              DetailColor="#503026" />
                </DataTemplate>
            </ListView.GroupHeaderTemplate>
            <!-- End Group Header Customization -->
        </ListView>
    </ContentPage.Content>
</ContentPage>
页眉和页脚
ListView 可以呈现随列表元素滚动的页眉和页脚。 页眉和页脚可以是文本字符串或更复杂的布局。 此行为与分区组不同。
可以将 Header 和/或 Footer 设置为 string 值,也可以将它们设置为更复杂的布局。 还有 HeaderTemplate 和 FooterTemplate 属性,可让你为支持数据绑定的页眉和页脚创建更复杂的布局。
若要创建基本的页眉/页脚,只需将“页眉”或“页脚”属性设置为要显示的文本即可。 在代码中:
ListView HeaderList = new ListView()
{
    Header = "Header",
    Footer = "Footer"
};
在 XAML 中:
<ListView x:Name="HeaderList" 
          Header="Header"
          Footer="Footer">
    ...
</ListView>

若要创建自定义页眉和页脚,请定义“页眉”和“页脚”视图:
<ListView.Header>
    <StackLayout Orientation="Horizontal">
        <Label Text="Header"
               TextColor="Olive"
               BackgroundColor="Red" />
    </StackLayout>
</ListView.Header>
<ListView.Footer>
    <StackLayout Orientation="Horizontal">
        <Label Text="Footer"
               TextColor="Gray"
               BackgroundColor="Blue" />
    </StackLayout>
</ListView.Footer>

滚动条可见性
ListView 类具有 HorizontalScrollBarVisibility 和 VerticalScrollBarVisibility 属性,这些属性获取或设置一个 ScrollBarVisibility 值,该值表示水平或垂直滚动条何时可见。 这两个属性都可以设置为以下值:
- Default指示平台的默认滚动条行为,并且是- HorizontalScrollBarVisibility和- VerticalScrollBarVisibility属性的默认值。
- Always指示滚动条将可见,即使内容大小适合视图。
- Never指示滚动条将不可见,即使内容大小不适合视图。
行分隔符
在 iOS 和 Android 上,默认情况下,分隔线显示在 ListView 元素之间。 如果你希望在 iOS 和 Android 上隐藏分隔线,请在 ListView 上设置 SeparatorVisibility 属性。 SeparatorVisibility 的选项包括:
- Default - 在 iOS 和 Android 上显示分隔线。
- None - 在所有平台上隐藏分隔符。
默认可见性:
C#:
SeparatorDemoListView.SeparatorVisibility = SeparatorVisibility.Default;
XAML:
<ListView x:Name="SeparatorDemoListView" SeparatorVisibility="Default" />

无:
C#:
SeparatorDemoListView.SeparatorVisibility = SeparatorVisibility.None;
XAML:
<ListView x:Name="SeparatorDemoListView" SeparatorVisibility="None" />

还可以通过 SeparatorColor 属性设置分隔线的颜色:
C#:
SeparatorDemoListView.SeparatorColor = Color.Green;
XAML:
<ListView x:Name="SeparatorDemoListView" SeparatorColor="Green" />

注意
加载 ListView 后在 Android 上设置这些属性中的任何一个都会导致很大的性能损失。
行高
默认情况下,ListView 中的所有行都具有相同的高度。 ListView 有两个可用于更改该行为的属性:
- HasUnevenRows–- true/- false值,如果设置为- true,则行具有不同的高度。 默认为- false。
- RowHeight– 当- HasUnevenRows为- false时设置每行的高度。
可以通过设置 ListView 上的 RowHeight 属性来设置所有行的高度。
自定义固定行高度
C#:
RowHeightDemoListView.RowHeight = 100;
XAML:
<ListView x:Name="RowHeightDemoListView" RowHeight="100" />

不均匀行
如果希望各行有不同的高度,可以将 HasUnevenRows 属性设置为 true。 将 HasUnevenRows 设置为 true 后,无需手动设置行高,因为高度将由 Xamarin.Forms 自动计算。
C#:
RowHeightDemoListView.HasUnevenRows = true;
XAML:
<ListView x:Name="RowHeightDemoListView" HasUnevenRows="true" />

在运行时重设行大小
如果 HasUnevenRows 属性设置为 true,则可在运行时以编程方式重设各个 ListView 行的大小。 Cell.ForceUpdateSize 方法会更新单元格的大小,即使单元格当前不可见,如以下代码示例所示:
void OnImageTapped (object sender, EventArgs args)
{
    var image = sender as Image;
    var viewCell = image.Parent.Parent as ViewCell;
    if (image.HeightRequest < 250) {
        image.HeightRequest = image.Height + 100;
        viewCell.ForceUpdateSize ();
    }
}
OnImageTapped 事件处理程序的执行是为了响应单元格中的 Image 被点击的操作,该处理程序会增加单元格中显示的 Image 的大小,使之便于查看。

警告
过度使用运行时行重设大小可能会导致性能下降。