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
相关产品推荐
相关产品推荐

