配置 CollectionView 项选择

浏览示例。 浏览示例

.NET 多平台应用 UI (.NET MAUI) CollectionView 定义控制项选择的以下属性:

  • SelectionMode,类型 SelectionMode为选择模式。
  • SelectedItem,类型 object为列表中的选定项。 此属性的默认绑定模式为 TwoWay,在未选择任何项时具有 null 值。
  • SelectedItems,类型 IList<object>为列表中的选定项。 此属性具有默认绑定模式 OneWay,并且未选择任何项时具有 null 值。
  • SelectionChangedCommand,类型 ICommand,在所选项更改时执行。
  • SelectionChangedCommandParameter 属于 object 类型,是传递给 SelectionChangedCommand 的参数。

所有这些属性都由 BindableProperty 对象提供支持,这意味着这些属性可以作为数据绑定的目标。

默认情况下, CollectionView 选择处于禁用状态。 但是,可以通过将 SelectionMode 属性值设置为 SelectionMode 枚举成员之一来更改此行为。

  • None – 指示无法选择项目。 这是默认值。
  • Single – 表示可以唯一地选择一个单项,并且所选项会被突出显示。
  • Multiple – 指示可以选择多个项,其中突出显示了选定项。

CollectionView 定义了一个事件,当 SelectionChanged 属性因用户选择列表中项或应用程序设置该属性而更改时,该事件会触发。 此外,当此 SelectedItems 属性发生更改时,也会触发该事件。 SelectionChanged事件附带的SelectionChangedEventArgs对象有两个属性,这两个属性的类型均为IReadOnlyList<object>

  • PreviousSelection – 所选项的列表,在所选内容发生更改之前。
  • CurrentSelection – 在选择更改后选中的项列表。

此外, CollectionView 还有一个 UpdateSelectedItems 方法,该方法使用所选项的列表更新 SelectedItems 属性,同时仅触发单个更改通知。

单选

当属性SelectionMode设置为Single时,可以在CollectionView中选择一个项目。 选择某个项后,该 SelectedItem 属性将设置为所选项的值。 当此属性发生更改时,SelectionChangedCommand 会执行(SelectionChangedCommandParameter 的值将传递给 ICommand),并触发 SelectionChanged 事件。

以下 XAML 示例展示了一个 CollectionView,它能够响应单个项的选择:

<CollectionView ItemsSource="{Binding Monkeys}"
                SelectionMode="Single"
                SelectionChanged="OnCollectionViewSelectionChanged">
    ...
</CollectionView>

等效的 C# 代码为:

CollectionView collectionView = new CollectionView
{
    SelectionMode = SelectionMode.Single
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty,  static (MonkeysViewModel vm) => vm.Monkeys);
collectionView.SelectionChanged += OnCollectionViewSelectionChanged;

在此代码示例中,SelectionChanged事件触发时会执行OnCollectionViewSelectionChanged事件处理程序,该处理程序会检索之前选定的项和当前选定的项。

void OnCollectionViewSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    string previous = (e.PreviousSelection.FirstOrDefault() as Monkey)?.Name;
    string current = (e.CurrentSelection.FirstOrDefault() as Monkey)?.Name;
    ...
}

重要

更改SelectionMode属性而引发的更改可以触发SelectionChanged事件。

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

CollectionView 垂直列表(单选)的屏幕截图。

多项选择

当属性 SelectionMode 设置为 Multiple时,可以选择该属性中的 CollectionView 多个项。 当选择项被选中时,SelectedItems 属性将设置为被选中的项。 当此属性发生更改时,会执行SelectionChangedCommand(将SelectionChangedCommandParameter的值传递给ICommand),并触发SelectionChanged事件。

以下 XAML 示例展示了一个 CollectionView,它可以响应多项选择。

<CollectionView ItemsSource="{Binding Monkeys}"
                SelectionMode="Multiple"
                SelectionChanged="OnCollectionViewSelectionChanged">
    ...
</CollectionView>

等效的 C# 代码为:

CollectionView collectionView = new CollectionView
{
    SelectionMode = SelectionMode.Multiple
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty,  static (MonkeysViewModel vm) => vm.Monkeys);
collectionView.SelectionChanged += OnCollectionViewSelectionChanged;

在此代码示例中,当SelectionChanged事件触发时,将执行OnCollectionViewSelectionChanged事件处理程序,该事件处理程序会检索以前选定的项和当前选定的项。

void OnCollectionViewSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    var previous = e.PreviousSelection;
    var current = e.CurrentSelection;
    ...
}

重要

更改SelectionMode属性可以触发该SelectionChanged事件。

以下屏幕截图显示 CollectionView 中的多个项选择:

具有多个选择的 CollectionView 垂直列表的屏幕截图。

单个预选

SelectionMode属性设置为Single时,可以通过将SelectedItem属性设置为CollectionView中的某一项来预选该项。 以下 XAML 示例演示了一个CollectionView,该控件预先选择单个项:

<CollectionView ItemsSource="{Binding Monkeys}"
                SelectionMode="Single"
                SelectedItem="{Binding SelectedMonkey}">
    ...
</CollectionView>

等效的 C# 代码为:

CollectionView collectionView = new CollectionView
{
    SelectionMode = SelectionMode.Single
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty,  static (MonkeysViewModel vm) => vm.Monkeys);
collectionView.SetBinding(SelectableItemsView.SelectedItemProperty,  static (MonkeysViewModel vm) => vm.SelectedMonkey);

注释

SelectedItem 属性的默认绑定模式为 TwoWay.

属性 SelectedItem 的数据绑定到连接的视图模型的属性 SelectedMonkey,该属性是类型 Monkey。 默认情况下, TwoWay 使用绑定,以便当用户更改所选项时,属性 SelectedMonkey 的值将设置为所选 Monkey 对象。 该 SelectedMonkey 属性在 MonkeysViewModel 类中定义,并设置为 Monkeys 集合的第四项。

public class MonkeysViewModel : INotifyPropertyChanged
{
    ...
    public ObservableCollection<Monkey> Monkeys { get; private set; }

    Monkey selectedMonkey;
    public Monkey SelectedMonkey
    {
        get
        {
            return selectedMonkey;
        }
        set
        {
            if (selectedMonkey != value)
            {
                selectedMonkey = value;
            }
        }
    }

    public MonkeysViewModel()
    {
        ...
        selectedMonkey = Monkeys.Skip(3).FirstOrDefault();
    }
    ...
}

因此,当CollectionView出现时,会预先选择列表中的第四项。

具有单个预选的 CollectionView 垂直列表的屏幕截图。

多项预选

当属性 SelectionMode 设置为 Multiple时,可以预先选择该属性中的 CollectionView 多个项。 下面的 XAML 示例演示了一个 CollectionView,可用于预先选择多个项目:

<CollectionView x:Name="collectionView"
                ItemsSource="{Binding Monkeys}"
                SelectionMode="Multiple"
                SelectedItems="{Binding SelectedMonkeys}">
    ...
</CollectionView>

等效的 C# 代码为:

CollectionView collectionView = new CollectionView
{
    SelectionMode = SelectionMode.Multiple
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty,  static (MonkeysViewModel vm) => vm.Monkeys);
collectionView.SetBinding(SelectableItemsView.SelectedItemsProperty,  static (MonkeysViewModel vm) => vm.SelectedMonkeys);

注释

SelectedItems 属性的默认绑定模式为 OneWay.

属性 SelectedItems 被绑定到连接的视图模型的属性 SelectedMonkeys,其类型为 ObservableCollection<object>。 该 SelectedMonkeys 属性在类中 MonkeysViewModel 定义,并设置为集合中的 Monkeys 第二项、第四项和第五项:

namespace CollectionViewDemos.ViewModels
{
    public class MonkeysViewModel : INotifyPropertyChanged
    {
        ...
        ObservableCollection<object> selectedMonkeys;
        public ObservableCollection<object> SelectedMonkeys
        {
            get
            {
                return selectedMonkeys;
            }
            set
            {
                if (selectedMonkeys != value)
                {
                    selectedMonkeys = value;
                }
            }
        }

        public MonkeysViewModel()
        {
            ...
            SelectedMonkeys = new ObservableCollection<object>()
            {
                Monkeys[1], Monkeys[3], Monkeys[4]
            };
        }
        ...
    }
}

因此,当CollectionView出现时,列表中的第二项、第四项和第五项会被预先选择:

具有多个预选的 CollectionView 垂直列表的屏幕截图。

清除选择

SelectedItemSelectedItems属性可以通过将它们或它们绑定的对象设置为null来清除。 当清除其中任一属性时,会触发SelectionChanged事件,CurrentSelection属性为空,并执行SelectionChangedCommand

句柄重新选择

一种常见情况是,用户在CollectionView中选择一个项目,然后导航到另一个页面。 导航回时,该项仍处于选中状态,这将导致它们无法重新选择给定的项目。 若要启用重新选择,您应该清除 CollectionView 上的项目选择。

<CollectionView ...
                SelectionChanged="OnCollectionViewSelectionChanged" />

等效的 C# 代码为:

CollectionView collectionView = new CollectionView();
collectionView.SelectionChanged += OnCollectionViewSelectionChanged;

以下示例显示了事件的 SelectionChanged 事件处理程序代码:

void OnCollectionViewSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    var cv = (CollectionView)sender;
    if (cv.SelectedItem == null)
        return;

    cv.SelectedItem = null;
}

更改所选项目颜色

CollectionView具有一个SelectedVisualState,可用于在CollectionView中启动对所选项目的视觉更改。 常见的 VisualState 用例是改变选中项目的背景颜色,如以下 XAML 示例所示:

<ContentPage ...>
    <ContentPage.Resources>
        <Style TargetType="Grid">
            <Setter Property="VisualStateManager.VisualStateGroups">
                <VisualStateGroupList>
                    <VisualStateGroup x:Name="CommonStates">
                        <VisualState x:Name="Normal" />
                        <VisualState x:Name="Selected">
                            <VisualState.Setters>
                                <Setter Property="BackgroundColor"
                                        Value="LightSkyBlue" />
                            </VisualState.Setters>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateGroupList>
            </Setter>
        </Style>
    </ContentPage.Resources>
    <Grid Margin="20">
        <CollectionView ItemsSource="{Binding Monkeys}"
                        SelectionMode="Single">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <Grid Padding="10">
                        ...
                    </Grid>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </Grid>
</ContentPage>

重要

包含SelectedVisualStateStyle必须具有一个TargetType属性值,该属性值应是DataTemplate的根元素类型,该根元素被设置为ItemTemplate属性值。

包含视觉状态的样式的等效 C# 代码为:

using static Microsoft.Maui.Controls.VisualStateManager;
...

Setter backgroundColorSetter = new() { Property = BackgroundColorProperty, Value = Colors.LightSkyBlue };
VisualState stateSelected = new() { Name = CommonStates.Selected, Setters = { backgroundColorSetter } };
VisualState stateNormal = new() { Name = CommonStates.Normal };
VisualStateGroup visualStateGroup = new() { Name = nameof(CommonStates), States = { stateSelected, stateNormal } };
VisualStateGroupList visualStateGroupList = new() { visualStateGroup };
Setter vsgSetter = new() { Property = VisualStateGroupsProperty, Value = visualStateGroupList };
Style style = new(typeof(Grid)) { Setters = { vsgSetter } };

// Add the style to the resource dictionary
Resources.Add(style);

在此示例中, Style.TargetType 属性值设置为 Grid 因为根元素 ItemTemplate 是一个 Grid。 指定当CollectionView中的某项被选中时,SelectedVisualState将该项的BackgroundColor设置为LightSkyBlue

具有自定义单选颜色的 CollectionView 垂直列表的屏幕截图。

有关视觉状态的详细信息,请参阅 视觉状态

禁用选择

CollectionView 选择功能默认禁用。 但是,如果 CollectionView 已启用选择功能,可以通过将 SelectionMode 属性设为 None 来禁用它。

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

等效的 C# 代码为:

CollectionView collectionView = new CollectionView
{
    ...
    SelectionMode = SelectionMode.None
};

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

注释

当选择一个项目并将SelectionMode属性从Single更改为None时,SelectedItem属性将被设置为null,并且SelectionChanged事件将使用空的CurrentSelection属性触发。