You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MAUI中用CommunityToolkit.Mvvm筛选State=false的Task至CollectionView

解决方案

MAUI 确实没有 WPF 里的 ICollectionView 接口,但结合 CommunityToolkit.Mvvm 框架,有几种简洁的方式实现 CollectionView 展示 State=false 的 Task 数据:

方案一:ViewModel 维护过滤后的只读集合

在 ViewModel 中保留原始的 ObservableCollection<TaskItem>,同时暴露一个根据 State 过滤的只读属性,绑定到 CollectionView 的 ItemsSource。需要监听集合变更和属性变更,触发过滤集合的更新。

步骤1:定义 TaskItem 模型(使用 ObservableProperty)

using CommunityToolkit.Mvvm.ComponentModel;

public partial class TaskItem : ObservableObject
{
    [ObservableProperty]
    private bool _state;

    [ObservableProperty]
    private string _taskName;

    // 可添加其他任务属性
}

步骤2:实现 ViewModel

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Linq;

public partial class TasksViewModel : ObservableObject
{
    [ObservableProperty]
    private ObservableCollection<TaskItem> _allTasks = new();

    // 过滤后的任务集合,只返回 State=false 的项
    public IReadOnlyCollection<TaskItem> FilteredTasks => AllTasks.Where(t => !t.State).ToList();

    public TasksViewModel()
    {
        // 初始化测试数据
        InitTestTasks();

        // 监听原始集合的增删变更,触发过滤集合更新
        AllTasks.CollectionChanged += (_, __) => OnPropertyChanged(nameof(FilteredTasks));

        // 监听每个 TaskItem 的 State 属性变更,触发过滤集合更新
        foreach (var task in AllTasks)
        {
            task.PropertyChanged += Task_PropertyChanged;
        }
    }

    private void Task_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        if (e.PropertyName == nameof(TaskItem.State))
        {
            OnPropertyChanged(nameof(FilteredTasks));
        }
    }

    // 添加新任务的示例命令
    [RelayCommand]
    private void AddNewTask()
    {
        var newTask = new TaskItem 
        { 
            State = false, 
            TaskName = $"新任务 {AllTasks.Count + 1}" 
        };
        newTask.PropertyChanged += Task_PropertyChanged;
        AllTasks.Add(newTask);
    }

    private void InitTestTasks()
    {
        AllTasks.Add(new TaskItem { State = false, TaskName = "完成UI原型设计" });
        AllTasks.Add(new TaskItem { State = true, TaskName = "梳理接口文档" });
        AllTasks.Add(new TaskItem { State = false, TaskName = "编写单元测试" });
    }
}

步骤3:XAML 绑定

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:vm="clr-namespace:YourNamespace.ViewModels"
             x:Class="YourNamespace.Views.TasksPage">
    <ContentPage.BindingContext>
        <vm:TasksViewModel />
    </ContentPage.BindingContext>

    <CollectionView ItemsSource="{Binding FilteredTasks}">
        <CollectionView.ItemTemplate>
            <DataTemplate>
                <HorizontalStackLayout Padding="10">
                    <Label Text="{Binding TaskName}" FontSize="16" VerticalOptions="Center" />
                    <Switch IsToggled="{Binding State}" Margin="0,0,10,0" HorizontalOptions="EndAndExpand" />
                </HorizontalStackLayout>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
</ContentPage>

方案二:使用 FilteredObservableCollection(需额外安装包)

借助 Microsoft.Toolkit.Collections 中的 FilteredObservableCollection,它内置了过滤逻辑,能自动处理集合变更,只需在属性变化时刷新过滤条件即可。

步骤1:安装 NuGet 包

安装 Microsoft.Toolkit.Collections 包(与 CommunityToolkit.Mvvm 兼容)。

步骤2:实现 ViewModel

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.Toolkit.Collections;
using System.Collections.ObjectModel;

public partial class TasksViewModel : ObservableObject
{
    public FilteredObservableCollection<TaskItem> FilteredTasks { get; }

    public TasksViewModel()
    {
        var allTasks = new ObservableCollection<TaskItem>
        {
            new TaskItem { State = false, TaskName = "完成UI原型设计" },
            new TaskItem { State = true, TaskName = "梳理接口文档" },
            new TaskItem { State = false, TaskName = "编写单元测试" }
        };

        // 初始化过滤集合,指定过滤条件:State=false
        FilteredTasks = new FilteredObservableCollection<TaskItem>(allTasks, t => !t.State);

        // 监听每个 TaskItem 的 State 变化,刷新过滤
        foreach (var task in allTasks)
        {
            task.PropertyChanged += (_, e) =>
            {
                if (e.PropertyName == nameof(TaskItem.State))
                {
                    FilteredTasks.RefreshFilter();
                }
            };
        }
    }

    [RelayCommand]
    private void AddNewTask()
    {
        var newTask = new TaskItem 
        { 
            State = false, 
            TaskName = $"新任务 {FilteredTasks.SourceCollection.Count + 1}" 
        };
        newTask.PropertyChanged += (_, e) =>
        {
            if (e.PropertyName == nameof(TaskItem.State))
            {
                FilteredTasks.RefreshFilter();
            }
        };
        ((ObservableCollection<TaskItem>)FilteredTasks.SourceCollection).Add(newTask);
    }
}

步骤3:XAML 绑定

与方案一的 XAML 代码一致,直接绑定 FilteredTasks 即可。

方案对比

  • 方案一:无需额外依赖,实现简单,但每次过滤会生成新的集合实例,适合数据量不大的场景。
  • 方案二:基于官方工具包的过滤集合,性能更优,自动处理集合增删,适合数据量较大或频繁变更的场景。

内容的提问来源于stack exchange,提问作者olololool

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 07:55:42