问题

我正在try 使用CollectionViewMvvM进行多项 Select .(official docs)在区分正常的代码隐藏和MVVM方面做得不是很好,对我们新手来说,这很糟糕.

我可以让单项 Select 工作,但要跳到多项 Select 是我做不到的.

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

单选

以下是单项 Select 的工作代码:

将类型为PersonObservableCollection传递给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();
    }
}

在视图中,创建一个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命令:如果用户对他们 Select 的SelectedPerson感到满意,我将它传递回它来自的页面,否则我将 Select 设为空并返回:

[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;
}

多项 Select

经过多次努力,下面是可用的代码.very important:注意集合绑定中使用的ObservableCollection的类型(提示,它是Object).

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

我当前的代码与上面的代码相同,但我将显示全部的视图模型和视图,以及应该填充的列表的屏幕截图.

视图模型:

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>

推荐答案

在您的VM中创建一个属性(请注意,它需要是一个object的集合(请参见this question)

[ObservableProperty]
private ObservableCollection<Person> persons;

[ObservableProperty]
private ObservableCollection<object> selectedPersons;

初始化它们

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

然后把你的CollectionView元Bundle 在一起

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

如果用户 Select 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

Csharp相关问答推荐

ITypeLib2.GetLibStatistics()在C#中总是抛出AccessViolationException

在一个模拟上设置一个方法,该模拟具有一个参数,该参数是一个numc函数表达式

在实时数据库中匹配两个玩家的问题

WeakReference未被垃圾收集

使用HttpResponseMessage中的嵌套列表初始化JSON

异步实体框架核心查询引发InvalidOperation异常

为基本审计设置Audit.EntityFramework.Core

C#使用TextFieldParser读取.csv,但无法使用";0";替换创建的列表空条目

每个http请求需要60秒,为什么?

将字节转换为 struct 并返回

使用ExtractIconEx(或其他方式)提取最大的可用图标

如何在发布NuGet包之前设置命名空间?

数据库操作预计影响1行,但实际影响0行; after _dbContext.SaveChanges();

DropDownListFor未显示选定值

RavenDb:为什么在字符串==空的情况下过滤会过滤得太多?

try 访问字典中的模拟对象时引发KeyNotFoundException

最小API定义的Swagger标头参数

我是否以错误的方式使用了异步延迟初始化?

使用生产环境调试我的应用程序的快速方法

Windows 10上埃及标准时间的时区偏移不正确