c# - .Net MAUI : How to select single and multiple items using MVVM and CollectionView

标签 c# mvvm maui collectionviewsource multipleselection

问题

我正在尝试使用 CollectionViewMvvM 进行多项选择。 ( official docs 并没有很好地区分正常的代码隐藏和 MVVM,对于我们这些菜鸟来说,这是很痛苦的。

我可以进行单选,但无法实现多选。

我将展示我的单选工作代码,并讨论如何使其适用于多选。也许有人比我知道更多?

单选

这是单选的工作代码:

Person 类型的 ObservableCollection 传递给 ModelView。声明一个 Person 实例,它将成为“选定的对象”。

namespace Sandbox.ViewModel;

[QueryProperty("Persons", "Persons")]
public partial class SelectPageViewModel : ObservableObject
{
    [ObservableProperty]
    private ObservableCollection<Person> persons;

    [ObservableProperty]
    private Person selectedPerson;

    public SelectPageViewModel()
    {
        Persons = new();
    }
}

在 View 中,创建一个 CollectionView 并对其属性做出一些好的猜测:

<Grid>
    <Label Text="Select from List"/>

    <CollectionView ItemsSource="{Binding Persons}"
                    SelectionMode="Single"
                    SelectedItem="{Binding SelectedPerson}"
                    SelectionChangedCommand="{Binding SelectionChangedCommand}">
        <CollectionView.ItemTemplate>
            <DataTemplate x:DataType="model:Person">
                <Grid>
                    <Label Text="{Binding Name}"/>
                </Grid>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
</Grid>

回到 ViewModel 中,SelectionChanged 命令:如果用户对他们的 SelectedPerson 选择感到满意,我会将其传回其来源的页面,否则我取消选择并返回:

[RelayCommand]
private async Task SelectionChanged() 
{
    bool keepSelection = await App.Current.MainPage.DisplayAlert(SelectedPerson.Name, "Keep this selection?", "Yes", "No");
    if (keepSelection)
    {
        Dictionary<string, object> throwParam = new()
        {
            { "SelectedPerson", SelectedPerson }
        };
        await Shell.Current.GoToAsync("..", throwParam);
    }

    // else clear the selection and return
    SelectedPerson = null;
    return;
}

多项选择

经过一番努力,这里是工作代码。非常重要的事情:请注意用于绑定(bind)到集合的 ObservableCollection 的类型(提示,它是 Object)。

另一个编辑(我当前的代码)

我当前的代码与上面的代码相同,但我将总共显示 ViewModel 和 View,以及应该填充的列表的屏幕截图。

View 模型:

namespace Sandbox.ViewModel;

[QueryProperty("Persons","Persons")]
public partial class SelectPageViewModel : ObservableObject
{
    [ObservableProperty]
    private ObservableCollection<Person> persons;

    [ObservableProperty]
    private ObservableCollection<Object> selectedPersons;

    [ObservableProperty]
    private Person selectedPerson;

    public SelectPageViewModel()
    {
        Persons = new();
        SelectedPersons = new();
    }


    [RelayCommand]
    private void SelectionChanged()
    {
// every time something is selected, the object is added to SelectedPersons automagically.
        int a = SelectedPersons.Count; // will +1 every time
    }
}

查看:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:viewmodel="clr-namespace:Sandbox.ViewModel"
             xmlns:model="clr-namespace:Sandbox.Model"
             x:DataType="viewmodel:SelectPageViewModel"
             x:Class="Sandbox.View.SelectPage"
             Title="SelectPage">

    <Grid RowDefinitions="Auto,Auto" Padding="10">
        <Label Grid.Row="0"
               Text="Select from List"
               FontSize="Large"
               FontAttributes="Bold" />

        <CollectionView Grid.Row="1"
                        ItemsSource="{Binding Persons}"                    
                        SelectionMode="Multiple"
                        SelectedItems="{Binding SelectedPersons, Mode=TwoWay}"
                        SelectionChangedCommand="{Binding SelectionChangedCommand}">
            <CollectionView.ItemTemplate>
                <DataTemplate x:DataType="model:Person">
                    <Grid Padding="10">
                        <Label Text="{Binding Name}"
                               FontSize="Medium" />
                    </Grid>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </Grid>
</ContentPage>

最佳答案

在虚拟机中创建一个属性(请注意,它需要是对象的集合(请参阅 this question)

[ObservableProperty]
private ObservableCollection<Person> persons;

[ObservableProperty]
private ObservableCollection<object> selectedPersons;

初始化它们

public SelectPageViewModel()
{
    Persons = new();
    SelectedPersons = new();
}

然后将您的CollectionView绑定(bind)到它

 <CollectionView ItemsSource="{Binding Persons}"
                SelectionMode="Multiple"
                SelectedItems="{Binding SelectedPersons}"
                SelectionChangedCommand="{Binding SelectionChangedCommand}">

如果用户选择 3 行,这 3 个对象将包含在 SelectedPersons 中。 SelectedPersons 将是您的 ItemsSource Persons

的子集
[RelayCommand]
private void SelectionChanged()
{
    foreach(var p in SelectedPersons)
    {
       if (p is Person person)
        {
            Console.WriteLine($"{person.Name} is selected");
        }
    }
}

[ObservableProperty]
private ObservableCollection<Person> persons;

[ObservableProperty]
private ObservableCollection<object> selectedPersons

关于c# - .Net MAUI : How to select single and multiple items using MVVM and CollectionView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77208180/

相关文章:

c# - 有没有办法在 TabControl 中禁用 TabPage?

c# - 从 Javascript 更改时,HiddenField.ValueChanged 事件未触发

c# - 使用 MVVM 进行正确验证

c# - 创建新的 .NET 6 MAUI 项目

c# - 获取 "The entity type <model> is not part of the model for the current context."

mvvm - 使用TextWatcher获取editText的旧值

基于绑定(bind)数据类型的WPF弹出选择模板

android - 如何在 MAUI 中创建 Android 前台服务

c# - 信任其他 CA 并在 net6 MAUI 解决方案中使用 Android 证书存储

c# - 如何将鼠标焦点设置到 WPF 数据网格的行详细信息?