列表视图和网格视图

大多数应用都会操纵和显示数据集,例如图像库或一组电子邮件。 XAML UI 框架提供了轻松显示和操控应用数据的 ListView 和 GridView 控件。

注意

ListView 和 GridView 都派生自 ListViewBase 类,因此它们具有相同的功能,但以不同的方式显示数据。 在本文中,除非另有指定,否则有关 列表视图 的讨论同时适用于 ListView 和 GridView 控件。 我们可能会引用 ListView 或 ListViewItem 等类,但 List 前缀可使用相应网格等效项(GridView 或 GridViewItem)的 Grid 代替 。

使用集合时,ListView 和 GridView 控件提供了许多好处。 两者都易于实现并提供基本的 UI、交互和滚动,同时易于自定义。 两者都可以绑定到现有的动态数据源或 XAML 本身或代码隐藏中提供的硬编码数据。

这两个控件都可以灵活地用于各种方案,但总的来说,它们最适合所有项具有相同的基本结构和外观以及相同的交互行为的集合。 也就是说,单击它们时应执行相同的操作 (例如打开链接或浏览) 。

比较 ListView 和 GridView

ListView

ListView 控件显示垂直堆叠在单个列中的数据。 ListView 更适用于将文本作为焦点的项目,以及要从上到下阅读的集合 (例如,按字母顺序排序) 。 ListView 的几个常见用例包括消息列表和搜索结果。 如果需要以多个列或类似表的格式显示集合,则 不应 使用 ListView。 相反,请考虑使用 DataGrid 控件。

按字母顺序分组的数据的列表视图的屏幕截图。

GridView

GridView 控件以行和列形式呈现可垂直滚动的项集合。 数据水平堆叠,直到填充列,然后继续列中的下一行。 GridView 更适用于具有图像作为焦点的集合,或者其项可以从一边到一边读取或不按特定顺序排序的集合。 GridView 的一个常见用例是照片或产品库。

显示为网格视图的照片的内容库的屏幕截图。

应使用哪个集合控件? 与 ItemsRepeater 的比较

在决定使用哪种控件之前,请务必了解这些类型的控件之间的差异。

ListView 和 GridView

功能丰富的 ListView 和 GridView 控件 现成工作。 它们不需要自定义,但可以轻松自定义。 每个集合都有自己的内置 UI 和 UX,旨在按原样显示几乎任何类型的集合。

ItemsRepeater

ItemsRepeater 控件也用于显示集合,但它被设计为创建自定义控件的构建基块,以满足特定的 UI 要求。 它的内置特性和功能与 ListView 和 GridView 不同,因此需要实现任何必要的功能或交互。 如果你有一个高度自定义的 UI,而你无法使用 ListView 或 GridView 创建,或者数据源需要每个项的不同行为,请使用 ItemsRepeater。

阅读 ItemsRepeater 指南API 文档,详细了解 ItemsRepeater。

UWP 和 WinUI 2

重要

本文中的信息和示例针对使用 Windows 应用 SDKWinUI 3 的应用进行优化,但通常适用于使用 WinUI 2 的 UWP 应用。 有关特定于平台的信息和示例,请参阅 UWP API 参考。

本部分包含你在 UWP 或 WinUI 2 应用中使用该控件所需的信息。

这些控件的 API 存在于 Windows.UI.Xaml.Controls 命名空间中。

建议使用最新的 WinUI 2 来获取所有控件的最新样式和模板。

创建列表视图或网格视图

打开 WinUI 3 库应用,查看 ListViewGridView 的实际应用。

WinUI 3 库应用包括大多数 WinUI 3 控件、特性和功能的交互式示例。 通过 Microsoft Store 获取应用,或在 GitHub 上获取源代码

ListView 和 GridView 的类型都是 ItemsControl,因此它们可以包含任何类型的项的集合。 ListView 或 GridView 控件必须在其 Items 集合中具有项,然后才能在屏幕上显示任何内容。 若要填充视图,可以直接 将项添加到集合, 或将 ItemsSource 属性设置为数据源。

注意

可以使用 Items 或 ItemsSource 属性填充列表,但不能同时使用这两者。 如果你设置 ItemsSource 属性并使用 XAML 添加项目,将忽略添加的项目。 如果 ItemsSource 属性已设置且使用代码向项集合中添加项,则会引发异常。

为简单起见,本文中的许多示例直接填充 Items 集合。 但是,列表中的项更常见于来自动态源,例如来自联机数据库的书籍列表。 出于此目的,你使用 ItemsSource 属性。

向 ListView 或 GridView 控件添加项

可以使用 XAML 或代码将项添加到 ListView 或 GridView 集合,以生成相同的结果。 如果有少量项不会更改且易于定义,或者如果在运行时在代码中生成项,则通常会通过 XAML 添加项。

方法 1:将项添加到 Items 集合

  • 选项 1:通过 XAML 添加项

    <!-- No corresponding C# code is needed for this example. -->
    
    <ListView x:Name="Fruits">
    <x:String>Apricot</x:String>
    <x:String>Banana</x:String>
    <x:String>Cherry</x:String>
    <x:String>Orange</x:String>
    <x:String>Strawberry</x:String>
    </ListView>
    
  • 选项 2:通过代码添加项

    <StackPanel Name="FruitsPanel"></StackPanel>
    
    // Create a new ListView and add content.
    ListView Fruits = new ListView();
    Fruits.Items.Add("Apricot");
    Fruits.Items.Add("Banana");
    Fruits.Items.Add("Cherry");
    Fruits.Items.Add("Orange");
    Fruits.Items.Add("Strawberry");
    
    // Add the ListView to a parent container in the visual tree (which you created in the corresponding XAML file).
    FruitsPanel.Children.Add(Fruits);
    

这两个选项生成相同的列表视图,如下所示:

显示水果列表的简单列表视图的屏幕截图。

方法 2:通过设置 ItemsSource 属性添加项

通常使用 ListView 或 GridView 来显示来自源(如数据库或 Internet)的数据。 若要从数据源填充 ListView 或 GridView 控件,需要将其 ItemsSource 属性设置为数据项的集合。 如果 ListView 或 GridView 要保存自定义类对象,则此方法效果更好,如以下示例所示。

  • 选项 1:在代码中设置 ItemsSource

    此处,ListView ItemsSource 属性在代码中直接设置为集合的实例。

    <StackPanel x:Name="ContactPanel"></StackPanel>
    
    // Class definition should be provided within the namespace being used, outside of any other classes.
    
    this.InitializeComponent();
    
    // Instead of adding hard coded items to an ObservableCollection as shown here,
    //the data could be pulled asynchronously from a database or the internet.
    ObservableCollection<Contact> Contacts = new ObservableCollection<Contact>();
    
    // You create Contact objects by providing a first name, last name, and company for the Contact constructor.
    // They are then added to the ObservableCollection Contacts.
    Contacts.Add(new Contact("John", "Doe", "Contoso, LTD."));
    Contacts.Add(new Contact("Jane", "Doe", "Fabrikam, Inc."));
    Contacts.Add(new Contact("Santa", "Claus", "Alpine Ski House"));
    
    // Create a new ListView (or GridView) for the UI, and add content by setting ItemsSource
    ListView ContactsLV = new ListView();
    ContactsLV.ItemsSource = Contacts;
    
    // Add the ListView to a parent container in the visual tree (which you created in the corresponding XAML file)
    ContactPanel.Children.Add(ContactsLV);
    
  • 选项 2:使用 XAML 设置 ItemsSource

    还可以将 ItemsSource 属性绑定到 XAML 中的集合。 在此处,ItemsSource 绑定到名为 Contacts 的公共属性,该属性公开页面的私人数据收集(名为 _contacts)。

    <ListView x:Name="ContactsLV" ItemsSource="{x:Bind Contacts}"/>
    
    // Provide a class definition within the namespace being used, outside of any other classes.
    // These two declarations belong outside the main page class.
    private ObservableCollection<Contact> _contacts = new ObservableCollection<Contact>();
    
    public ObservableCollection<Contact> Contacts
    {
        get { return this._contacts; }
    }
    
    // Define this method within your main page class.
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);
    
        // Instead of hard coded items, the data could be pulled
        // asynchronously from a database or the internet.
        Contacts.Add(new Contact("John", "Doe", "Contoso, LTD."));
        Contacts.Add(new Contact("Jane", "Doe", "Fabrikam, Inc."));
        Contacts.Add(new Contact("Santa", "Claus", "Alpine Ski House"));
    }
    

这两个选项将生成相同的列表视图,如以下屏幕截图所示。 (列表视图显示每个项的字符串表示形式,因为未为此练习定义数据模板。)

显示设置了 ItemsSource 属性的简单列表视图的屏幕截图。

重要

如果没有已定义的数据模板,仅当自定义类对象具有定义的 ToString 方法时,才会在列表视图中显示其字符串值。

下一部分将更详细地介绍如何在 ListView 或 GridView 模板中正确直观地表示简单类项和自定义类项。

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

注意

如果需要在列表视图中显示分组数据,则必须绑定到 CollectionViewSource 类。 CollectionViewSource 充当 XAML 中集合类的代理,并启用分组支持。 有关详细信息,请参阅 CollectionViewSource

使用数据模板自定义外观

通过在 ListView 或 GridView 控件中使用数据模板,可以定义项和数据可视化的方式。 在默认情况下,数据项以绑定到的数据对象的字符串表现形式显示在列表视图中。 通过将 DisplayMemberPath 设置为该属性,可以显示数据项的特定属性的字符串表示形式。

但是,你通常可能希望显示更丰富的数据表示形式。 若要指定列表视图或网格视图中项的显示方式,请创建 DataTemplate 类。 DataTemplate 中的 XAML 定义用于显示单个项的控件的布局和外观。 布局中的控件可以绑定到数据对象的属性,也可以具有内联定义的静态内容。

重要

在 DataTemplate 中使用 x:Bind 标记扩展 时,必须在数据模板上指定数据类型 (x:DataType) 。

简单的 ListView 数据模板

在此示例中,数据项是简单的字符串。 若要在字符串左侧添加图像,并用青色显示字符串,请在 ListView 定义中内联定义 DataTemplate。 这是之前使用方法 1 下的选项 1 创建的相同 ListView 控件。

<!--No corresponding code is needed for this example.-->
<ListView x:Name="FruitsList">
                <ListView.ItemTemplate>
                    <DataTemplate x:DataType="x:String">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="47"/>
                                <ColumnDefinition/>
                            </Grid.ColumnDefinitions>
                            <Image Source="Assets/placeholder.png" Width="32" Height="32"
                                HorizontalAlignment="Left" VerticalAlignment="Center"/>
                            <TextBlock Text="{x:Bind}" Foreground="Teal" FontSize="14"
                                Grid.Column="1" VerticalAlignment="Center"/>
                        </Grid>
                    </DataTemplate>
                </ListView.ItemTemplate>
                <x:String>Apricot</x:String>
                <x:String>Banana</x:String>
                <x:String>Cherry</x:String>
                <x:String>Orange</x:String>
                <x:String>Strawberry</x:String>
            </ListView>

下面是应用简单 ListView 数据模板时数据项的显示方式:

应用简单 ListView 数据模板后显示的列表的屏幕截图。

自定义类对象的 ListView 数据模板

在以下示例中,数据项是 Contact 对象。 若要在联系人姓名和公司左侧添加联系人图像,请在 ListView 定义中内联定义 DataTemplate。 此 ListView 数据模板是在方法 2 下的选项 2 中创建的,如前所述。

<ListView x:Name="ContactsLV" ItemsSource="{x:Bind Contacts}">
    <ListView.ItemTemplate>
        <DataTemplate x:DataType="local:Contact">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Image Grid.Column="0" Grid.RowSpan="2" Source="Assets/grey-placeholder.png" Width="32"
                    Height="32" HorizontalAlignment="Center" VerticalAlignment="Center"></Image>
                <TextBlock Grid.Column="1" Text="{x:Bind Name}" Margin="12,6,0,0"
                    Style="{ThemeResource BaseTextBlockStyle}"/>
                <TextBlock  Grid.Column="1" Grid.Row="1" Text="{x:Bind Company}" Margin="12,0,0,6"
                    Style="{ThemeResource BodyTextBlockStyle}"/>
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

下面是为自定义类对象应用 ListView 数据模板时数据项的显示方式:

应用自定义类对象的 ListView 数据模板后显示的列表的屏幕截图。

使用数据模板是定义 ListView 外观的主要方法。 如果列表包含大量项,它们也可能显著影响性能。

可以在 ListView 或 GridView 定义中内联定义数据模板,如前面的代码所示,也可以单独在 Resources 节中定义。 如果在 ListView 或 GridView 定义之外定义它,则必须为数据模板提供 x:Key 属性,并使用该键将其分配给 ListView 或 GridView 的 ItemTemplate 属性。

有关如何使用数据模板和项目容器定义列表或网格中的项目的外观的更多信息和示例,请参阅项目容器和模板

更改项的布局

将项添加到 ListView 或 GridView 控件时,它会自动包装项容器中的每个项,然后布局所有项容器。 这些项容器的布局方式取决于控件的 ItemsPanel 属性。

  • 默认情况下,ListView 使用 ItemsStackPanel 生成垂直列表:

    显示项垂直列表的简单列表视图的屏幕截图。

  • GridView 使用 ItemsWrapGrid,可水平添加项,并垂直环绕和滚动:

    显示项目水平列表的简单网格视图的屏幕截图。

可以通过调整项面板上的属性来修改项的布局,也可以将默认面板替换为另一个面板。

注意

如果更改 ItemsPanel, 请不要 禁用虚拟化。 ItemsStackPanel 和 ItemsWrapGrid 都支持虚拟化,因此这些类是安全的。 如果你使用任何其他面板,可能会禁用虚拟化,并且降低列表视图的性能。 有关详细信息,请参阅性能下的列表视图文章。

此示例演示如何通过更改 ItemsStackPanel 的 Orientation 属性,使 ListView 控件在水平列表中布局其项容器。

由于列表视图是垂直滚动的,因此默认情况下,还需要调整列表视图的内部 ScrollViewer 上的一些属性,使其水平滚动。

重要

以下示例显示列表视图宽度不受约束,因此不会显示水平滚动条。 如果运行此代码,则可以为 ListView 设置 Width="180" 以显示滚动条。

<ListView Height="60"
          ScrollViewer.HorizontalScrollMode="Enabled"
          ScrollViewer.HorizontalScrollBarVisibility="Auto"
          ScrollViewer.VerticalScrollMode="Disabled"
          ScrollViewer.VerticalScrollBarVisibility="Hidden">
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <ItemsStackPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
    <x:String>Apricot</x:String>
    <x:String>Banana</x:String>
    <x:String>Cherry</x:String>
    <x:String>Orange</x:String>
    <x:String>Strawberry</x:String>
</ListView>

列表的显示方式如下:

水平列表视图的屏幕截图。

在下一个示例中,ListView 通过使用 ItemsWrapGrid(而不是 ItemsStackPanel)在垂直包装列表中对项目进行布局。

重要

必须约束列表视图的高度,以强制控件包装容器。

<ListView Height="100"
          ScrollViewer.HorizontalScrollMode="Enabled"
          ScrollViewer.HorizontalScrollBarVisibility="Auto"
          ScrollViewer.VerticalScrollMode="Disabled"
          ScrollViewer.VerticalScrollBarVisibility="Hidden">
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <ItemsWrapGrid/>
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
    <x:String>Apricot</x:String>
    <x:String>Banana</x:String>
    <x:String>Cherry</x:String>
    <x:String>Orange</x:String>
    <x:String>Strawberry</x:String>
</ListView>

列表的显示方式如下:

具有网格布局的列表视图的屏幕截图。

如果在列表视图中显示分组数据,ItemsPanel 将确定项组的布局方式,而不是各个项的布局方式。例如,如果使用前面显示的水平 ItemsStackPanel 来显示分组数据,则组将水平排列,但每个组中的项仍垂直堆叠,如下所示:

分组水平列表视图的屏幕截图

项目选择和交互

可以选择多种方法,让用户与列表视图交互。 默认情况下,用户可以选择单个项。 你可以更改 SelectionMode 属性以启用多选或禁用选择。 可以设置 IsItemClickEnabled 属性,以便用户单击项 (例如,按钮) 调用操作,而不是选择该项。

注意

ListView 和 GridView 对其 SelectionMode 属性使用 ListViewSelectionMode 枚举。 IsItemClickEnabled 默认设置为 False ,因此只需将其设置为启用单击模式。

此表显示用户可与列表视图交互的方式以及响应交互的方式。

若要启用此交互: 使用这些设置: 处理此事件: 使用此属性以获取选定的项目:
无交互 SelectionMode=“None”
IsItemClickEnabled=“False”
空值 N/A
单选 SelectionMode=“Single”
IsItemClickEnabled=“False”
SelectionChanged SelectedItem
SelectedIndex
多重选择 SelectionMode=“Multiple”
IsItemClickEnabled=“False”
SelectionChanged SelectedItems
扩展选择 SelectionMode=“Extended”
IsItemClickEnabled=“False”
SelectionChanged SelectedItems
单击 SelectionMode=“None”
IsItemClickEnabled=“True”
ItemClick 空值

注意

可以启用 IsItemClickEnabled 以引发 ItemClick 事件,同时 SelectionMode 也设置为 SingleMultipleExtended。 如果你执行此操作,将先后引发 ItemClick 事件和 SelectionChanged 事件。 例如,在某些情况下 (,如果转到 ItemClick 事件处理程序) 中的另一页,则不会引发 SelectionChanged 事件,也不会选择该项。

可以在 XAML 或代码中设置这些属性,如下所示:

<ListView x:Name="myListView" SelectionMode="Multiple"/>

<GridView x:Name="myGridView" SelectionMode="None" IsItemClickEnabled="True"/>
myListView.SelectionMode = ListViewSelectionMode.Multiple;

myGridView.SelectionMode = ListViewSelectionMode.None;
myGridView.IsItemClickEnabled = true;

只读

你可以将 SelectionMode 属性设置为 ListViewSelectionMode.None 以禁用项目选择。 这会使控件处于只读模式,因此它用于显示数据,但不能用于与之交互。 也就是说,已禁用项选择,但控件本身未禁用。

单选

下表介绍 SelectionMode 设置为 Single 时键盘、鼠标和触摸交互。

修改键 交互
  • 用户可以使用空格键、鼠标单击或点击来选择单个项。
  • Ctrl
  • 用户可以使用空格键、鼠标单击或点击来取消选择单个项。
  • 通过使用箭头键,用户可以独立于所选内容移动焦点。
  • 当 SelectionMode 设置为 Single 时,可以从 SelectedItem 属性获取所选数据项。 可以使用 SelectedIndex 属性获取所选项的集合中的索引。 如果没有选择任何项目,则 SelectedItem 为 null,并且 SelectedIndex 为 -1。

    如果尝试将不在 Items 集合中的项设置为 SelectedItem,则会忽略该操作,SelectedItem 为 null。 但是,如果尝试将 SelectedIndex 设置为列表项范围之外索引,则会发生 System.ArgumentException 异常。

    多重选择

    下表描述了 SelectionMode 设置为 “多”时键盘、鼠标和触摸交互。

    修改键 交互
  • 用户可以使用空格键、鼠标单击或点击选择焦点项来选择多个项。
  • 通过使用箭头键,用户可以移动焦点,不受其选择。
  • 移位
  • 用户可以通过单击或点击所选内容中的第一项,然后单击或点击所选内容中的最后一项来选择多个连续项。
  • 通过使用箭头键,用户可以从选择 Shift 键时选择的项开始选择连续项。
  • 扩展选择

    下表介绍 SelectionMode 设置为 Extended 时键盘、鼠标和触摸交互。

    修改键 交互
  • 该行为与 Single 选择相同。
  • Ctrl
  • 用户可以使用空格键、鼠标单击或点击选择焦点项来选择多个项。
  • 通过使用箭头键,用户可以独立于所选内容移动焦点。
  • 移位
  • 用户可以通过单击或点击所选内容中的第一项,然后单击或点击所选内容中的最后一项来选择多个连续项。
  • 通过使用箭头键,用户可以从选择 Shift 键时选择的项开始选择连续项。
  • 当 SelectionMode 设置为 “多”“扩展”时,可以从 SelectedItems 属性获取所选数据项。

    SelectedIndex、SelectedItem 和 SelectedItems 属性已同步。 例如,如果将 SelectedIndex 设置为 -1,则 SelectedItem 设置为 null ,SelectedItems 为空。 如果将 SelectedItem 设置为 null,SelectedIndex 将设置为 -1,SelectedItems 为空。

    在多选模式下,SelectedItem 包含第一个选择的项目,而 Selectedindex 包含第一个选择的项目的索引。

    响应选择更改

    若要响应列表视图中的选择更改,请处理 SelectionChanged 事件。 在事件处理程序代码中,可以从 SelectionChangedEventArgs.AddedItems 属性获取选择项列表。 你可以获取从 SelectionChangedEventArgs.RemovedItems 属性取消选择的任何项目。 AddedItems 和 RemovedItems 集合最多包含一项,除非用户通过按住 Shift 键选择一系列项。

    以下示例演示如何处理 SelectionChanged 事件并访问各种 Item 集合:

    <StackPanel HorizontalAlignment="Right">
        <ListView x:Name="listView1" SelectionMode="Multiple"
                  SelectionChanged="ListView1_SelectionChanged">
            <x:String>Apricot</x:String>
            <x:String>Banana</x:String>
            <x:String>Cherry</x:String>
            <x:String>Orange</x:String>
            <x:String>Strawberry</x:String>
        </ListView>
        <TextBlock x:Name="selectedItem"/>
        <TextBlock x:Name="selectedIndex"/>
        <TextBlock x:Name="selectedItemCount"/>
        <TextBlock x:Name="addedItems"/>
        <TextBlock x:Name="removedItems"/>
    </StackPanel>
    
    private void ListView1_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (listView1.SelectedItem != null)
        {
            selectedItem.Text =
                "Selected item: " + listView1.SelectedItem.ToString();
        }
        else
        {
            selectedItem.Text =
                "Selected item: null";
        }
        selectedIndex.Text =
            "Selected index: " + listView1.SelectedIndex.ToString();
        selectedItemCount.Text =
            "Items selected: " + listView1.SelectedItems.Count.ToString();
        addedItems.Text =
            "Added: " + e.AddedItems.Count.ToString();
        removedItems.Text =
            "Removed: " + e.RemovedItems.Count.ToString();
    }
    

    单击模式

    可以更改列表视图,以便用户单击按钮和其他项,而不是选择它们。 例如,当用户单击列表或网格中的项时,应用打开新页面时,此功能非常有用。

    若要启用此行为:

    • 将 SelectionMode 设置为 None
    • 将 IsItemClickEnabled 设置为 True
    • 处理 ItemClick 事件以在用户单击某个项目时执行某些操作。

    下面是具有可单击项的列表视图。 ItemClick 事件处理程序中的代码会在应用中打开一个新页面。

    <ListView SelectionMode="None"
              IsItemClickEnabled="True"
              ItemClick="ListView1_ItemClick">
        <x:String>Page 1</x:String>
        <x:String>Page 2</x:String>
        <x:String>Page 3</x:String>
        <x:String>Page 4</x:String>
        <x:String>Page 5</x:String>
    </ListView>
    
    private void ListView1_ItemClick(object sender, ItemClickEventArgs e)
    {
        switch (e.ClickedItem.ToString())
        {
            case "Page 1":
                this.Frame.Navigate(typeof(Page1));
                break;
    
            case "Page 2":
                this.Frame.Navigate(typeof(Page2));
                break;
    
            case "Page 3":
                this.Frame.Navigate(typeof(Page3));
                break;
    
            case "Page 4":
                this.Frame.Navigate(typeof(Page4));
                break;
    
            case "Page 5":
                this.Frame.Navigate(typeof(Page5));
                break;
    
            default:
                break;
        }
    }
    

    以编程方式选择项目的范围

    有时,可能需要以编程方式操作 ListView 项选择。 例如,可以显示“ 全部选择” 按钮,以允许用户选择列表中的所有项目。 在这种情况下,从 SelectedItems 集合中逐个添加和删除项通常不太高效。 每项更改都会导致 SelectionChanged 事件,并且当你直接使用项而不是使用索引值时,该项将取消虚拟化。

    使用 SelectAllSelectRangeDeselectRange 方法来修改所选内容比使用 SelectedItems 属性更高效。 这些方法使用项索引范围选择 (或取消选择) 项。 虚拟化的项目将保持虚拟化状态,因为仅使用了索引。 指定范围中的所有项目均已选定(或已取消选定),无论初始选择状态是什么。 SelectionChanged 事件在每次调用这些方法时仅发生一次。

    重要

    仅当 SelectionMode 属性设置为 MultipleExtended 时,才应调用这些方法。 如果在 SelectionMode 为 SingleNone 时调用 SelectRange,则会引发异常。

    使用索引范围选择项时,请使用 SelectedRanges 属性获取列表中的所有选定区域。

    如果 ItemsSource 属性实现 IItemsRangeInfo,并且使用这些方法来修改所选内容,则 SelectionChangedEventArgs 中不会设置 AddedItems 和 RemovedItems 属性。 设置这些属性需要对项目对象执行取消虚拟化操作。 改为使用 SelectedRanges 属性获取项目。

    通过调用 SelectAll 方法,可以选择集合中的所有项目。 但是没有相应的方法来取消选择所有项目。 你可以通过以下方法取消选择所有项目:调用 DeselectRange,并传递 FirstIndex 值为 0 并且 Length 值等于集合中项目数的 ItemIndexRange。 以下示例中显示了这一点,以及用于选择所有项的选项。

    <StackPanel Width="160">
        <Button Content="Select all" Click="SelectAllButton_Click"/>
        <Button Content="Deselect all" Click="DeselectAllButton_Click"/>
        <ListView x:Name="listView1" SelectionMode="Multiple">
            <x:String>Apricot</x:String>
            <x:String>Banana</x:String>
            <x:String>Cherry</x:String>
            <x:String>Orange</x:String>
            <x:String>Strawberry</x:String>
        </ListView>
    </StackPanel>
    
    private void SelectAllButton_Click(object sender, RoutedEventArgs e)
    {
        if (listView1.SelectionMode == ListViewSelectionMode.Multiple ||
            listView1.SelectionMode == ListViewSelectionMode.Extended)
        {
            listView1.SelectAll();
        }
    }
    
    private void DeselectAllButton_Click(object sender, RoutedEventArgs e)
    {
        if (listView1.SelectionMode == ListViewSelectionMode.Multiple ||
            listView1.SelectionMode == ListViewSelectionMode.Extended)
        {
            listView1.DeselectRange(new ItemIndexRange(0, (uint)listView1.Items.Count));
        }
    }
    

    有关如何更改所选项目外观的信息,请参阅项目容器和模板

    拖放

    ListView 和 GridView 控件支持在其自己的控件内以及它们与其他 ListView 和 GridView 控件之间拖放项。 有关实现拖放功能的详细信息,请参阅 拖放

    获取示例代码