.NET Maui实现无额外内存分配的ObservableCollection过滤方案问询
解决方案:基于ICollectionView实现无内存重分配的即时过滤
核心思路
利用.NET原生的ICollectionView接口,在原始ObservableCollection之上提供过滤能力——无需重新创建集合,同时完整保留原始集合的可观测特性,ListView/CollectionView可直接绑定该视图作为数据源。
具体实现步骤
1. 定义ViewModel结构
在ViewModel中维护原始数据集合和对应的ICollectionView实例,同时实现搜索文本绑定与过滤逻辑:
using System.Collections.ObjectModel; using System.ComponentModel; using System.Windows.Data; public class MainViewModel : INotifyPropertyChanged { // 原始数据集合,保留可观测特性 private ObservableCollection<ItemModel> _originalItems; public ObservableCollection<ItemModel> OriginalItems { get => _originalItems; set { _originalItems = value; OnPropertyChanged(nameof(OriginalItems)); // 初始化视图并绑定过滤方法 ItemsView = CollectionViewSource.GetDefaultView(OriginalItems); ItemsView.Filter += FilterItems; } } // 绑定到列表控件的视图 private ICollectionView _itemsView; public ICollectionView ItemsView { get => _itemsView; set { _itemsView = value; OnPropertyChanged(nameof(ItemsView)); } } // 搜索文本绑定属性 private string _searchText; public string SearchText { get => _searchText; set { _searchText = value; OnPropertyChanged(nameof(SearchText)); // 搜索文本变化时触发过滤刷新 ItemsView?.Refresh(); } } // 自定义过滤逻辑 private bool FilterItems(object item) { if (string.IsNullOrWhiteSpace(SearchText)) return true; if (item is ItemModel model) { // 根据业务需求调整匹配规则,支持多字段、大小写忽略等 return model.Name.IndexOf(SearchText, StringComparison.OrdinalIgnoreCase) >= 0 || model.Description.IndexOf(SearchText, StringComparison.OrdinalIgnoreCase) >= 0; } return false; } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } // 示例数据模型 public class ItemModel { public string Name { get; set; } public string Description { get; set; } }
2. XAML绑定配置
将ListView的ItemsSource绑定到ViewModel的ItemsView,SearchBar绑定到SearchText:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:vm="clr-namespace:YourProjectNamespace" x:Class="YourProjectNamespace.MainPage"> <ContentPage.BindingContext> <vm:MainViewModel /> </ContentPage.BindingContext> <VerticalStackLayout> <SearchBar Text="{Binding SearchText, Mode=TwoWay}" Placeholder="输入关键词搜索"/> <ListView ItemsSource="{Binding ItemsView}"> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <VerticalStackLayout Padding="10"> <Label Text="{Binding Name}" FontSize="Large"/> <Label Text="{Binding Description}" FontSize="Small" TextColor="Gray"/> </VerticalStackLayout> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> </VerticalStackLayout> </ContentPage>
3. 关键特性说明
ICollectionView基于原始ObservableCollection工作,过滤仅调整项的可见性,不会触发集合内存重分配- 原始集合的增删改操作会自动同步到视图,完整保留可观测特性
- 过滤逻辑可灵活扩展,支持正则匹配、多字段组合等复杂规则
- 若使用Maui推荐的CollectionView,绑定方式完全一致,仅需替换ListView标签即可
内容的提问来源于stack exchange,提问作者YMC
相关产品推荐
相关产品推荐

