添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

.NET 多平台应用 UI (.NET MAUI) ListView 显示可选择数据项的可滚动垂直列表。 虽然 ListView 管理列表的外观,但列表中每个项的外观由 DataTemplate 使用 Cell 来显示项的 定义。 .NET MAUI 包括用于显示文本和图像组合的单元格类型,还可以定义显示所需任何内容的自定义单元格。 ListView 还包括对显示页眉和页脚、分组数据、拉取刷新和上下文菜单项的支持。

ListView 派生自 ItemsView<Cell> 类,该类继承了以下属性:

  • ItemsSource ,类型 IEnumerable 为 ,指定要显示的项的集合,其默认值 null 为 。
  • ItemTemplate ,类型 DataTemplate 为 ,指定要应用于要显示的项集合中的每个项的模板。
  • ListView 定义以下属性:

  • Footer ,类型 object 为 ,指定将在列表末尾显示的字符串或视图。
  • FooterTemplate ,类型 DataTemplate 为 ,指定要 DataTemplate 用于设置 格式的 Footer
  • GroupHeaderTemplate ,类型 DataTemplate 为 ,定义 DataTemplate 用于定义每个组的标头的外观。 此属性与 GroupDisplayBinding 属性互斥。 因此,将此属性设置为 GroupDisplayBinding null
  • HasUnevenRows 类型 bool 为 ,指示列表中的项是否可以具有不同高度的行。 此属性的默认值为 false
  • Header ,类型 object 为 ,指定将在列表开头显示的字符串或视图。
  • HeaderTemplate ,类型 DataTemplate 为 ,指定要 DataTemplate 用于设置 格式的 Header
  • HorizontalScrollBarVisibility ,类型 ScrollBarVisibility 为 ,指示水平滚动条何时可见。
  • IsGroupedEnabled 类型 bool 为 ,指示基础数据是否应在组中显示。 此属性的默认值为 false
  • IsPullToRefreshEnabled 类型 bool 为 ,指示用户是否可以向下轻扫以刷新 ListView 其数据。 此属性的默认值为 false
  • IsRefreshing 类型 bool 为 ,指示 当前是否 ListView 正在刷新。 此属性的默认值为 false
  • RefreshCommand ,类型 ICommand 为 ,表示将在触发刷新时执行的命令。
  • RefreshControlColor 类型 Color 为 ,确定刷新时显示的刷新可视化效果的颜色。
  • RowHeight 类型 int 为 时,确定每行 HasUnevenRows false 的高度。
  • SelectedItem ,类型 object 为 ,表示 中 ListView 当前选定的项。
  • SelectionMode ,类型 ListViewSelectionMode 为 ,指示是否可以在 中选择 ListView 项。 此属性的默认值为 Single
  • SeparatorColor ,类型 Color 为 ,定义分隔列表中项的条形的颜色。
  • SeparatorVisibility 类型为 SeparatorVisibility ,定义分隔符在项之间是否可见。
  • VerticalScrollBarVisibility 类型为 ScrollBarVisibility ,指示垂直滚动条何时可见。
  • 所有这些属性都由 BindableProperty 对象提供支持,这意味着它们可以成为数据绑定的目标并设置样式。

    此外, ListView 定义以下不受 对象支持 BindableProperty 的属性:

  • GroupDisplayBinding ,类型 BindingBase 为 ,用于显示组标头的绑定。 此属性与 GroupHeaderTemplate 属性互斥。 因此,将此属性设置为 GroupHeaderTemplate null
  • GroupShortNameBinding ,类型 BindingBase 为 ,用于在分组跳转列表中显示的名称的绑定。
  • CachingStrategy 类型 ListViewCachingStrategy 为 ,定义 的 ListView 单元格重用策略。 这是只读属性。
  • ListView 定义以下事件:

  • ItemAppearing ,在将项的视觉表示形式添加到 的视觉布局时引发。 ListView ItemVisibilityEventArgs 此事件附带的对象定义 Item Index 属性。
  • ItemDisappearing ,从 的视觉布局中删除项的视觉表示形式时引发。 ListView ItemVisibilityEventArgs 此事件附带的对象定义 Item Index 属性。
  • ItemSelected ,选择列表中的新项时引发。 SelectedItemChangedEventArgs 此事件附带的对象定义 SelectedItem SelectedItemIndex 属性。
  • ItemTapped ,在点击 中的 ListView 项时引发。 ItemTappedEventArgs 此事件附带的对象定义 Group Item ItemIndex 属性。
  • Refreshing ,在 上触发拉取刷新操作时引发。 ListView
  • Scrolled , . ScrolledEventArgs 此事件附带的对象定义 ScrollX ScrollY 属性。
  • ScrollToRequested . ScrollToRequestedEventArgs 此事件附带的对象定义 Element 、、 Mode Position ScrollX ScrollY ShouldAnimate 属性。
  • 使用数据填充 ListView

    ListView 通过将 属性 ItemsSource 设置为任何实现 IEnumerable 的集合来填充数据。

    ListView 如果在基础集合中添加、删除或更改项时需要刷新 ,则基础集合应是 IEnumerable 发送属性更改通知的集合,例如 ObservableCollection

    ListView 可以使用数据绑定将其 ItemsSource 属性 IEnumerable 绑定到集合来填充数据。 在 XAML 中,这是通过标记扩展实现的 Binding

    <ListView ItemsSource="{Binding Monkeys}" />
    

    等效 C# 代码如下:

    ListView listView = new ListView();
    listView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");
    

    在此示例中, ItemsSource 属性数据绑定到 Monkeys 连接的 viewmodel 的 属性。

    可以启用编译绑定以提高 .NET MAUI 应用程序中的数据绑定性能。 有关详细信息,请参阅 已编译的绑定

    有关数据绑定的详细信息,请参阅 数据绑定

    定义项外观

    可以通过将 属性设置为 ItemTemplateDataTemplate来定义 中ListView每个项的外观:

    <ListView ItemsSource="{Binding Monkeys}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <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>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    

    中指定的 DataTemplate 元素定义列表中每个项的外观,并且 的子元素 DataTemplate 必须是 Cell 对象。 在此示例中, 中的 DataTemplate 布局由 管理 GridGrid包含一个 Image 对象和两个 Label 对象,这些对象都绑定到 类的属性Monkey

    public class Monkey
        public string Name { get; set; }
        public string Location { get; set; }
        public string Details { get; set; }
        public string ImageUrl { get; set; }
    

    以下屏幕截图显示了对列表中每个项进行模板化的结果:

    有关数据模板的详细信息,请参阅 数据模板

    ListView 每个项的外观由 定义, DataTemplate并且 DataTemplate 必须引用 类 Cell 来显示项。 每个单元格表示 中的 ListView一个数据项。 .NET MAUI 包含以下内置单元格:

  • TextCell,在单独的行上显示主要文本和辅助文本。
  • ImageCell,它以单独的行显示主文本和辅助文本的图像。
  • SwitchCell,显示文本和可以打开或关闭的开关。
  • EntryCell,显示可编辑的标签和文本。
  • ViewCell,这是一个自定义单元格,其外观由 View定义。 如果要完全定义 中 ListView每个项的外观,应使用此单元格类型。
  • 通常, SwitchCellEntryCell 将仅用于 , TableView 不会在 中使用 ListView。 有关 和 EntryCell的详细信息SwitchCell,请参阅 TableView

    文本单元格

    TextCell 单独的行上显示主要文本和辅助文本。 TextCell 定义以下属性:

  • Text,类型 string为 ,定义要显示的主要文本。
  • TextColor,类型 Color为 ,表示主要文本的颜色。
  • Detail,类型 string为 ,定义要显示的辅助文本。
  • DetailColor,类型 Color为 ,指示辅助文本的颜色。
  • Command类型 ICommand为 ,定义在点击单元格时执行的命令。
  • CommandParameter,类型 object为 ,表示传递给 命令的参数。
  • 这些属性由 BindableProperty 对象提供支持;也就是说,它们可以作为数据绑定的目标,并能进行样式设置。

    以下示例演示如何使用 TextCell 定义 中 ListView项的外观:

    <ListView ItemsSource="{Binding Food}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <TextCell Text="{Binding Name}"
                          Detail="{Binding Description}" />
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    

    以下屏幕截图显示了生成的单元格外观:

    图像单元格

    ImageCell 单独的行上显示包含主要文本和辅助文本的图像。 ImageCellTextCell继承属性,并定义 ImageSource 类型的 ImageSource属性,该属性指定要在单元格中显示的图像。 此属性由 BindableProperty 对象支持,这意味着它可以是数据绑定的目标,并可以设置样式。

    以下示例演示如何使用 ImageCell 定义 中 ListView项的外观:

    <ListView ItemsSource="{Binding Food}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ImageCell ImageSource="{Binding Image}"
                           Text="{Binding Name}"
                           Detail="{Binding Description}" />
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    

    以下屏幕截图显示了生成的单元格外观:

    查看单元格

    ViewCell 一个自定义单元格,其外观由 View定义。 ViewCell定义 类型ViewView为 的属性,该属性定义表示单元格内容的视图。 此属性由 BindableProperty 对象支持,这意味着它可以是数据绑定的目标,并可以设置样式。

    由于 View 属性是 ViewCell 类的内容属性,因此不需要通过 XAML 显式设置。

    以下示例演示如何使用 ViewCell 定义 中 ListView项的外观:

    <ListView ItemsSource="{Binding Monkeys}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <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>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    

    ViewCell中,布局可由任何 .NET MAUI 布局管理。 在此示例中,布局由 管理 GridGrid包含一个 Image 对象和两个 Label 对象,这些对象都绑定到 类的属性Monkey

    以下屏幕截图显示了对列表中每个项进行模板化的结果:

    在运行时选择项外观

    可以通过将 属性设置为 ItemTemplateDataTemplateSelector 对象,在运行时根据项值选择 中每个ListView项的外观:

    <ContentPage ...
                 xmlns:templates="clr-namespace:ListViewDemos.Templates">
        <ContentPage.Resources>
            <DataTemplate x:Key="AmericanMonkeyTemplate">
                <ViewCell>
                </ViewCell>
            </DataTemplate>
            <DataTemplate x:Key="OtherMonkeyTemplate">
                <ViewCell>
                </ViewCell>
            </DataTemplate>
            <templates:MonkeyDataTemplateSelector x:Key="MonkeySelector"
                                                 AmericanMonkey="{StaticResource AmericanMonkeyTemplate}"
                                                 OtherMonkey="{StaticResource OtherMonkeyTemplate}" />
        </ContentPage.Resources>
        <StackLayout Margin="20">
            <ListView ItemsSource="{Binding Monkeys}"
                      ItemTemplate="{StaticResource MonkeySelector}" />
        </StackLayout>
    </ContentPage>
    

    属性 ItemTemplate 设置为 MonkeyDataTemplateSelector 对象。 下面的示例展示了 MonkeyDataTemplateSelector 类:

    public class MonkeyDataTemplateSelector : DataTemplateSelector
        public DataTemplate AmericanMonkey { get; set; }
        public DataTemplate OtherMonkey { get; set; }
        protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
            return ((Monkey)item).Location.Contains("America") ? AmericanMonkey : OtherMonkey;
    

    MonkeyDataTemplateSelector 定义 AmericanMonkey 设置为不同数据模板的 和 OtherMonkeyDataTemplate 属性。 当猴子名称包含“America”时,重写 OnSelectTemplate 将返回 AmericanMonkey 模板,该模板以青青蓝显示猴子名称和位置。 当猴子名称不包含“America”时, OnSelectTemplate 重写将 OtherMonkey 返回模板,该模板以银色显示猴子名称和位置:

    有关数据模板选择器的详细信息,请参阅 创建 DataTemplateSelector

    响应项选择

    默认情况下, ListView 选择处于启用状态。 但是,可以通过设置 SelectionMode 属性来更改此行为。 ListViewSelectionMode 枚举定义下列成员:

  • None – 指示无法选择项。
  • Single – 指示可以选择单个项,并突出显示所选项。 这是默认值。
  • ListView 定义属性 ItemSelected 更改时 SelectedItem 引发的事件,无论是由于用户从列表中选择项,还是应用设置属性。 SelectedItemChangedEventArgs此事件附带的对象具有 SelectedItemSelectedItemIndex 属性。

    当 属性 SelectionMode 设置为 Single时,可以选择 中的 ListView 单个项。 选择项后,属性 SelectedItem 将设置为所选项的值。 当此属性更改时, ItemSelected 将引发 事件。

    以下示例演示 ListView 了可以响应单个项目选择的 :

    <ListView ItemsSource="{Binding Monkeys}"
              ItemSelected="OnItemSelected">
    </ListView>
    

    在此示例中, OnItemSelected 事件处理程序在触发事件时 ItemSelected 执行,事件处理程序将检索所选项:

    void OnItemSelected(object sender, SelectedItemChangedEventArgs args)
        Monkey item = args.SelectedItem as Monkey;
    

    以下屏幕截图显示了 中的 ListView单个项选择:

    SelectedItem可以通过将属性或绑定到 的对象设置为 来null清除该属性。

    ListView 默认情况下,选择处于启用状态。 但是,可以通过将 属性设置为 SelectionModeNone来禁用它:

    <ListView ...
              SelectionMode="None" />
    

    当 属性 SelectionMode 设置为 None时,无法选择 中的 ListView 项,该 SelectedItem 属性将保留 null,并且 ItemSelected 不会触发事件。

    ListView 是用于显示数据的强大视图,但它有一些限制。 使用自定义单元格时,滚动性能可能会受到影响,尤其是当它们包含深层嵌套的视图层次结构或使用某些需要复杂度量的布局时。 幸运的是,可以使用一些技术来避免性能不佳。

    ListView通常用于显示比屏幕上适合的数据要多得多。 例如,音乐应用可能有一个包含数千个条目的歌曲库。 为每个条目创建一个项会浪费宝贵的内存,并且性能不佳。 不断创建和销毁行需要应用不断实例化和清理对象,这也会导致性能不佳。

    为了节省内存,每个平台的本机 ListView 等效项都具有用于重用行的内置功能。 只有屏幕上可见的单元格才会加载到内存中,内容将加载到现有单元格中。 此模式可防止应用实例化数千个对象,从而节省时间和内存。

    .NET MAUI 允许 ListView 通过 ListViewCachingStrategy 枚举重用单元格,该枚举定义了以下成员:

  • RetainElement,指定 ListView 将为列表中的每个项生成一个单元格。
  • RecycleElement,指定 ListView 将尝试通过回收列表单元格来最小化其内存占用和执行速度。
  • RecycleElementAndDataTemplate,同时RecycleElement确保 使用 DataTemplateSelectorListViewDataTemplate,对象按列表中的项类型进行缓存。
  • RetainElement缓存策略指定 ListView 将为列表中的每个项生成一个单元格,并且是默认ListView行为。 应在以下情况下使用它:

  • 每个单元格都有大量绑定 (20-30 多个) 。
  • 单元格模板经常更改。
  • 测试发现 RecycleElement 缓存策略会导致执行速度降低。
  • 使用自定义单元格时,必须认识到缓存策略的后果 RetainElement 。 每次创建单元格时,都需要运行任何单元格初始化代码,这可能每秒多次。 在这种情况下,在页面上使用的布局技术(如使用多个嵌套 StackLayout 对象)在用户滚动时实时设置和销毁它们时成为性能瓶颈。

    RecycleElement缓存策略指定 ListView 将尝试通过回收列表单元格来最大程度地减少内存占用和执行速度。 此模式并不总是提供性能改进,应执行测试以确定任何改进。 但是,它是首选选择,应在以下情况下使用:

  • 每个单元格都有少量到中等数量的绑定。
  • 每个单元格的 BindingContext 定义所有单元格数据。
  • 每个单元格大致相似,单元格模板不变。
  • 在虚拟化期间,单元格将更新其绑定上下文,因此,如果应用使用此模式,则必须确保正确处理绑定上下文更新。 有关单元格的所有数据都必须来自绑定上下文,否则可能会出现一致性错误。 使用数据绑定显示单元格数据可以避免此问题。 或者,单元格数据应在重写中 OnBindingContextChanged 设置,而不是在自定义单元格的构造函数中设置,如以下示例所示:

    public class CustomCell : ViewCell
        Image image = null;
        public CustomCell()
            image = new Image();
            View = image;
        protected override void OnBindingContextChanged()
            base.OnBindingContextChanged();
            var item = BindingContext as ImageItem;
            if (item != null)
                image.Source = item.ImageUrl;
    

    使用 DataTemplateSelector 回收元素

    ListView当 使用 DataTemplateSelector 选择 时DataTemplateRecycleElement缓存策略不会缓存DataTemplate对象。 而是为列表中的每一项数据选择 一个 DataTemplate

    缓存 RecycleElement 策略要求 DataTemplateSelector 当 要求选择 时 DataTemplate ,每个 DataTemplate 必须返回相同的 ViewCell 类型。 例如,如果给定一个 ListViewDataTemplateSelector ,其可以返回MyDataTemplateA (,其中MyDataTemplateA返回ViewCell) 类型的 MyViewCellA ,或者MyDataTemplateB (返回MyDataTemplateBViewCell) 类型的 MyViewCellB ,当返回 时MyDataTemplateA,必须返回MyViewCellA它,否则将引发异常。

    使用 DataTemplates 回收元素

    缓存RecycleElementAndDataTemplate策略基于RecycleElement缓存策略,另外确保当 ListView 使用 DataTemplateSelector 选择 时DataTemplateDataTemplate,对象按列表中的项类型进行缓存。 因此, DataTemplate 每个项类型选择一次对象,而不是每个项实例选择一次对象。

    RecycleElementAndDataTemplate缓存策略要求 DataTemplateDataTemplateSelector 返回的对象必须使用DataTemplate采用 的Type构造函数。

    设置缓存策略

    ListView可以通过在 XAML 中通过设置 属性来CachingStrategy定义缓存策略:

    <ListView CachingStrategy="RecycleElement">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    

    在 C# 中,缓存策略是通过构造函数重载设置的:

    ListView listView = new ListView(ListViewCachingStrategy.RecycleElement);
    

    在子类化 ListView 中设置缓存策略

    CachingStrategy在子类上ListView从 XAML 设置 属性不会生成所需的行为,因为 上ListView没有 CachingStrategy 属性。 此问题的解决方案是在子ListViewCachingStrategyListView上指定接受参数并将其传递给基类的构造函数:

    public class CustomListView : ListView
        public CustomListView (ListViewCachingStrategy strategy) : base (strategy)
    

    然后, ListViewCachingStrategy 可以使用 属性从 XAML x:Arguments 指定枚举值:

    <local:CustomListView>
        <x:Arguments>
            <ListViewCachingStrategy>RecycleElement</ListViewCachingStrategy>
        </x:Arguments>
    </local:CustomListView>
    

    页眉和页脚

    ListView 可以显示随列表中的项一起滚动的页眉和页脚。 页眉和页脚可以是字符串、视图或 DataTemplate 对象。

    ListView 定义用于指定页眉和页脚的以下属性:

  • Header类型 object为 ,指定将在列表开头显示的字符串、绑定或视图。
  • HeaderTemplate,属于 类型 DataTemplate,指定要 DataTemplate 用于设置 格式的 Header
  • Footer类型 object为 ,指定将在列表末尾显示的字符串、绑定或视图。
  • FooterTemplate,属于 类型 DataTemplate,指定要 DataTemplate 用于设置 格式的 Footer
  • 这些属性由 BindableProperty 对象提供支持,这意味着这些属性可以是数据绑定的目标。

    HeaderFooter和 属性可以设置为string值,如以下示例所示:

    <ListView ItemsSource="{Binding Monkeys}"
              Header="Monkeys"
              Footer="2022">
    </ListView>
    

    以下屏幕截图显示了生成的标头:

    HeaderFooter 属性都可以分别设置为视图。 这可以是单个视图,也可以是包含多个子视图的视图。 以下示例演示Header每个设置为StackLayout包含 Label 对象的 和 Footer 属性:

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

    以下屏幕截图显示了生成的标头:

    HeaderTemplateFooterTemplate 属性可以设置为DataTemplate用于设置页眉和页脚格式的对象。 在此方案中, HeaderFooter 属性必须绑定到要应用的模板的当前源,如以下示例所示:

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

    控制项分隔符

    默认情况下,在 iOS 和 Android 上的项之间 ListView 显示分隔符。 可以通过将 类型的 SeparatorVisibility属性设置为 SeparatorVisibilityNone更改此行为:

    <ListView ...
              SeparatorVisibility="None" />
    

    此外,启用分隔符后,可以使用 属性设置 SeparatorColor 其颜色:

    <ListView ...
              SeparatorColor="Blue" />
    

    调整项目大小

    默认情况下, 中的所有 ListView 项具有相同的高度,该高度派生自 DataTemplate 定义每个项外观的 的内容。 但是,可以使用 和 RowHeight 属性更改HasUnevenRows此行为。 默认情况下, HasUnevenRows 属性为 false

    可以将 RowHeight 属性设置为表示 intListView每个项的高度的 ,前提是 HasUnevenRowsfalse。 当 设置为 trueHasUnevenRows,中的每个ListView项可以具有不同的高度。 每个项的高度将派生自项的 DataTemplate的内容,因此每个项的大小将与其内容一起调整。

    如果 HasUnevenRows 属性为 true,则可以通过更改 中DataTemplate元素的布局相关属性,在运行时以编程方式调整各个ListView项的大小。 以下示例在点击对象时更改其高度 Image

    void OnImageTapped(object sender, EventArgs args)
        Image image = sender as Image;
        ViewCell viewCell = image.Parent.Parent as ViewCell;
        if (image.HeightRequest < 250)
          image.HeightRequest = image.Height + 100;
          viewCell.ForceUpdateSize();
    

    在此示例中, OnImageTapped 执行事件处理程序以响应 Image 正在点击的对象。 事件处理程序更新 的高度 Image ,方法 Cell.ForceUpdateSize 更新单元格的大小,即使当前不可见。

    过度使用动态项大小可能会导致 ListView 性能下降。

    从右到左布局

    ListView可以通过将其 属性设置为 RightToLeft来按从右到左的流方向布局其FlowDirection内容。 但是,理想情况下, FlowDirection 应在页面或根布局上设置 属性,这会导致页面或根布局中的所有元素响应流方向:

    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 x:Class="ListViewDemos.RightToLeftListPage"
                 Title="Right to left list"
                 FlowDirection="RightToLeft">
        <StackLayout Margin="20">
            <ListView ItemsSource="{Binding Monkeys}">
            </ListView>
        </StackLayout>
    </ContentPage>
    

    具有父元素的默认值 FlowDirectionMatchParent。 因此, ListViewStackLayout继承FlowDirection属性值,后者又从 ContentPage继承FlowDirection属性值。

    显示分组数据

    在不断滚动的列表中显示大型数据集时,通常会变得笨手笨脚。 在此方案中,将数据组织成组可以简化数据导航,从而改善用户体验。

    必须先对数据进行分组,然后才能显示数据。 这可以通过创建组列表来实现,其中每个组都是项列表。 组列表应该是一个 IEnumerable<T> 集合,其中 T 定义两个数据片段:

  • 定义 IEnumerable 属于组的项的集合。
  • 因此,对数据进行分组的过程是:

  • 创建为单个项建模的类型。
  • 创建一个为单个项组建模的类型。
  • 创建集合 IEnumerable<T> ,其中 T 是为单个项组建模的类型。 此集合是存储分组数据的组集合。
  • 将数据添加到集合。IEnumerable<T>
  • 对数据进行分组时,第一步是创建为单个项建模的类型。 下面的示例展示了 Animal 类:

    public class Animal
        public string Name { get; set; }
        public string Location { get; set; }
        public string Details { get; set; }
        public string ImageUrl { get; set; }
    

    类为 Animal 单个项建模。 然后,可以创建一个为一组项建模的类型。 下面的示例展示了 AnimalGroup 类:

    public class AnimalGroup : List<Animal>
        public string Name { get; private set; }
        public AnimalGroup(string name, List<Animal> animals) : base(animals)
            Name = name;
    

    AnimalGroup 继承自 类, List<T> 并添加表示 Name 组名称的属性。

    IEnumerable<T>然后可以创建组集合:

    public List<AnimalGroup> Animals { get; private set; } = new List<AnimalGroup>();
    

    此代码定义一个名为 的 Animals集合,其中集合中的每个项都是一个 AnimalGroup 对象。 每个 AnimalGroup 对象都包含一个名称和一个 List<Animal> 定义 Animal 组中对象的集合。

    然后,可将分组数据添加到集合:Animals

    Animals.Add(new AnimalGroup("Bears", new List<Animal>
        new Animal
            Name = "American Black Bear",
            Location = "North America",
            Details = "Details about the bear go here.",
            ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/0/08/01_Schwarzbär.jpg"
        new Animal
            Name = "Asian Black Bear",
            Location = "Asia",
            Details = "Details about the bear go here.",
            ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b7/Ursus_thibetanus_3_%28Wroclaw_zoo%29.JPG/180px-Ursus_thibetanus_3_%28Wroclaw_zoo%29.JPG"
        // ...
    Animals.Add(new AnimalGroup("Monkeys", new List<Animal>
        new Animal
            Name = "Baboon",
            Location = "Africa & Asia",
            Details = "Details about the monkey go here.",
            ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Papio_anubis_%28Serengeti%2C_2009%29.jpg/200px-Papio_anubis_%28Serengeti%2C_2009%29.jpg"
        new Animal
            Name = "Capuchin Monkey",
            Location = "Central & South America",
            Details = "Details about the monkey go here.",
            ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/4/40/Capuchin_Costa_Rica.jpg/200px-Capuchin_Costa_Rica.jpg"
        new Animal
            Name = "Blue Monkey",
            Location = "Central and East Africa",
            Details = "Details about the monkey go here.",
            ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/BlueMonkey.jpg/220px-BlueMonkey.jpg"
        // ...
    

    此代码在集合中创建两个 Animals 组。 第一个 AnimalGroup 名称为 Bears,包含 List<Animal> 熊详细信息的集合。 第二 AnimalGroup 个名称为 Monkeys,包含 List<Animal> 猴子详细信息的集合。

    ListView 将显示分组数据,前提是数据已正确分组,方法是将 IsGroupingEnabled 属性设置为 true

    <ListView ItemsSource="{Binding Animals}"
              IsGroupingEnabled="True">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <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>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    

    等效 C# 代码如下:

    ListView listView = new ListView
        IsGroupingEnabled = true
    listView.SetBinding(ItemsView.ItemsSourceProperty, "Animals");
    // ...
    

    中每个项 ListView 的外观是通过将其 ItemTemplate 属性设置为 DataTemplate来定义的。 有关详细信息,请参阅 定义项外观

    以下屏幕截图显示了显示 ListView 分组数据:

    默认情况下, ListView 将在组标头中显示组名称。 可以通过自定义组标头来更改此行为。

    自定义组标头

    可以通过将 属性设置为 ListView.GroupHeaderTemplateDataTemplate来自定义每个组标头的外观:

    <ListView ItemsSource="{Binding Animals}"
              IsGroupingEnabled="True">
        <ListView.GroupHeaderTemplate>
            <DataTemplate>
                <ViewCell>
                    <Label Text="{Binding Name}"
                           BackgroundColor="LightGray"
                           FontSize="18"
                           FontAttributes="Bold" />
                </ViewCell>
            </DataTemplate>
        </ListView.GroupHeaderTemplate>
    </ListView>
    

    在此示例中,每个组标头都设置为显示 Label 组名称的 ,并设置了其他外观属性。 以下屏幕截图显示了自定义的组标头:

    属性 GroupHeaderTemplateGroupDisplayBinding 属性互斥。 因此,不应同时设置这两个属性。

    不带模板的组

    ListView 可以显示正确分组的数据,而无需将 ItemTemplate 属性设置为 DataTemplate

    <ListView ItemsSource="{Binding Animals}"
              IsGroupingEnabled="true" />
    

    在此方案中,可以通过重写 ToString 为单个项建模的类型和为单个项组建模的类型中的 方法来显示有意义的数据。

    ListView 定义两 ScrollTo 种方法,用于将项目滚动到视图中。 其中一个重载将指定项滚动到视图中,而另一个重载将指定组中的指定项滚动到视图中。 这两个重载都有其他参数,这些参数允许指定滚动完成后项的确切位置,以及是否对滚动进行动画处理。

    ListView定义调用其中一ScrollTo种方法ScrollToRequested时触发的事件。 ScrollToRequestedEventArgs事件附带ScrollToRequested的 对象具有许多属性,包括 ShouldAnimateElementModePosition。 其中一些属性是从方法调用中指定的参数设置的 ScrollTo

    此外, ListView 定义触发 Scrolled 以指示发生滚动的事件。 ScrolledEventArgs事件附带的对象Scrolled具有 ScrollXScrollY 属性。

    ListView 定义触发 Scrolled 以指示发生滚动的事件。 ItemsViewScrolledEventArgs类表示事件附带的对象Scrolled,定义了以下属性:

  • ScrollX,类型 double为 ,表示滚动的 X 位置
  • ScrollY,类型 double为 ,表示滚动的 Y 位置。
  • 以下 XAML 示例演示一个 ListView ,它为 Scrolled 事件设置事件处理程序:

    <ListView Scrolled="OnListViewScrolled">
    </ListView>
    

    等效 C# 代码如下:

    ListView listView = new ListView();
    listView.Scrolled += OnListViewScrolled;
    

    在此代码示例中 OnListViewScrolled ,事件处理程序在触发事件时 Scrolled 执行:

    void OnListViewScrolled(object sender, ScrolledEventArgs e)
        // Custom logic
    

    对于 Scrolled 用户启动的滚动和编程滚动,将触发 事件。

    将项目滚动到视图中

    方法 ScrollTo 将指定的项滚动到视图中。 给定一 ListView 个名为 listView的对象,以下示例演示如何将 Proboscis Monkey 项滚动到视图中:

    MonkeysViewModel viewModel = BindingContext as MonkeysViewModel;
    Monkey monkey = viewModel.Monkeys.FirstOrDefault(m => m.Name == "Proboscis Monkey");
    listView.ScrollTo(monkey, ScrollToPosition.MakeVisible, true);
    

    或者,可以通过指定项和组,将分组数据中的项滚动到视图中。 以下示例演示如何将 Monkeys 组中的 Proboscis Monkey 项滚动到视图中:

    GroupedAnimalsViewModel viewModel = BindingContext as GroupedAnimalsViewModel;
    AnimalGroup group = viewModel.Animals.FirstOrDefault(a => a.Name == "Monkeys");
    Animal monkey = group.FirstOrDefault(m => m.Name == "Proboscis Monkey");
    listView.ScrollTo(monkey, group, ScrollToPosition.MakeVisible, true);
    

    调用 ScrollToRequested 方法时会 ScrollTo 触发 事件。

    禁用滚动动画

    将项滚动到视图中时,将显示滚动动画。 但是,可以通过将 方法的参数ScrollTo设置为 animatedfalse来禁用此动画:

    listView.ScrollTo(monkey, position: ScrollToPosition.MakeVisible, animate: false);
    

    控制滚动位置

    将项滚动到视图中时,可以使用 方法的 参数指定 position 滚动完成后项的 ScrollTo 确切位置。 此参数接受 ScrollToPosition 枚举成员。

    MakeVisible

    成员 ScrollToPosition.MakeVisible 指示应滚动该项,直到它在视图中可见:

    listView.ScrollTo(monkey, position: ScrollToPosition.MakeVisible, animate: true);
    

    成员 ScrollToPosition.Start 指示应将项滚动到视图的开头:

    listView.ScrollTo(monkey, position: ScrollToPosition.Start, animate: true);
    

    Center

    成员 ScrollToPosition.Center 指示应将项滚动到视图的中心:

    listView.ScrollTo(monkey, position: ScrollToPosition.Center, animate: true);
    

    成员 ScrollToPosition.End 指示应将项滚动到视图的末尾:

    listView.ScrollTo(monkey, position: ScrollToPosition.End, animate: true);
    

    滚动条可见性

    ListViewHorizontalScrollBarVisibility定义和VerticalScrollBarVisibility属性,它们由可绑定属性提供支持。 这些属性获取或设置一个 ScrollBarVisibility 枚举值,该值表示水平滚动条或垂直滚动条何时可见。 ScrollBarVisibility 枚举定义下列成员:

  • Default指示平台的默认滚动条行为,是 和 VerticalScrollBarVisibility 属性的HorizontalScrollBarVisibility默认值。
  • Always 指示滚动条将可见,即使内容适合视图。
  • Never 指示滚动条将不可见,即使内容不适合视图。
  • 添加上下文菜单

    ListView 支持上下文菜单项,这些项定义为 MenuItem 添加到每个项的 ViewCell.ContextActions 集合中的 DataTemplate 对象:

    <ListView x:Name="listView"
              ItemsSource="{Binding Monkeys}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <ViewCell.ContextActions>
                        <MenuItem Text="Favorite"
                                  Command="{Binding Source={x:Reference listView}, Path=BindingContext.FavoriteCommand}"
                                  CommandParameter="{Binding}" />
                        <MenuItem Text="Delete"
                                  Command="{Binding Source={x:Reference listView}, Path=BindingContext.DeleteCommand}"
                                  CommandParameter="{Binding}" />
                    </ViewCell.ContextActions>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    

    MenuItem右键单击 中的项时,ListView会显示 对象:

    ListView 支持拉取刷新功能,该功能允许通过下拉项列表来刷新显示的数据。

    若要启用要刷新的拉取,请将 IsPullToRefreshEnabled 属性设置为 true。 触发刷新时, ListView 引发 Refreshing 事件,并且 IsRefreshing 属性将设置为 true。 然后,刷新 的内容 ListView 所需的代码应由 事件的处理程序 Refreshing 执行,或由 ICommand 执行的实现 RefreshCommand 执行。 ListView刷新 后,IsRefreshing属性应设置为 false,或者EndRefresh应在 上ListView调用 方法,以指示刷新已完成。

    以下示例演示 ListView 了使用拉取刷新的 :

    <ListView ItemsSource="{Binding Animals}"
              IsPullToRefreshEnabled="true"
              RefreshCommand="{Binding RefreshCommand}"
              IsRefreshing="{Binding IsRefreshing}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    

    在此示例中,当用户启动刷新时, ICommand 将执行 由 RefreshCommand 属性定义的 ,这会刷新正在显示的项目。 刷新时会显示刷新可视化效果,其中包含一个动画进度圆圈。 属性的值 IsRefreshing 指示刷新操作的当前状态。 触发刷新时,此属性将自动转换为 true。 刷新完成后,应将 属性重置为 false