.NET MAUI中如何隐藏ObservableCollection标记删除的元素?
解决ObservableCollection过滤已删除项的问题
针对你用MVVM + Microsoft.Toolkit开发,需要隐藏deleted=true项的需求,给你几个实用方案:
方案1:利用ICollectionView做过滤(适合WPF/MAUI等UI框架)
大部分UI框架的CollectionView控件可直接绑定ICollectionView,通过设置过滤规则实现隐藏已删除项,无需修改原集合:
// ViewModel中实现 private ObservableCollection<YourModel> _sourceCollection; public ICollectionView FilteredCollection { get; } public YourViewModel() { _sourceCollection = new ObservableCollection<YourModel>(); FilteredCollection = CollectionViewSource.GetDefaultView(_sourceCollection); // 设置过滤规则:只保留未标记删除的项 FilteredCollection.Filter = item => { if (item is YourModel model) return !model.deleted; return false; }; }
将FilteredCollection绑定到UI的CollectionView控件即可。当源集合新增/删除项,或某条数据的deleted属性变化时,若模型实现了INotifyPropertyChanged,可监听属性变化自动调用FilteredCollection.Refresh()触发过滤更新。
方案2:使用Microsoft.Toolkit.Collections的FilteredObservableCollection
Microsoft.Toolkit.Collections库提供了FilteredObservableCollection<T>,它是ObservableCollection的子类,支持动态过滤,会自动监听源集合变化和项的属性变化:
先安装Microsoft.Toolkit.Collections NuGet包,再在ViewModel中使用:
using Microsoft.Toolkit.Collections; private ObservableCollection<YourModel> _sourceCollection; public FilteredObservableCollection<YourModel> FilteredCollection { get; } public YourViewModel() { _sourceCollection = new ObservableCollection<YourModel>(); // 初始化过滤集合,传入源集合和过滤条件 FilteredCollection = new FilteredObservableCollection<YourModel>(_sourceCollection, model => !model.deleted); }
此方案无需手动调用刷新,当源集合变化或模型deleted属性变更时(模型需实现INotifyPropertyChanged),过滤集合会自动更新,直接绑定到UI即可。
方案3:手动维护过滤后的ObservableCollection
若不想引入额外库,可手动创建过滤后的ObservableCollection,同时监听源集合变化和项的属性变化:
private ObservableCollection<YourModel> _sourceCollection; private ObservableCollection<YourModel> _filteredCollection; public ObservableCollection<YourModel> FilteredCollection => _filteredCollection; public YourViewModel() { _sourceCollection = new ObservableCollection<YourModel>(); // 初始化过滤集合 _filteredCollection = new ObservableCollection<YourModel>( _sourceCollection.Where(p => !p.deleted)); // 监听源集合的增删改变化 _sourceCollection.CollectionChanged += SourceCollection_CollectionChanged; // 给每个已存在的项监听deleted属性变化 foreach (var item in _sourceCollection) { if (item is INotifyPropertyChanged notifyItem) { notifyItem.PropertyChanged += Item_PropertyChanged; } } } private void SourceCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { switch (e.Action) { case NotifyCollectionChangedAction.Add: foreach (YourModel item in e.NewItems) { if (!item.deleted) _filteredCollection.Add(item); if (item is INotifyPropertyChanged notifyItem) { notifyItem.PropertyChanged += Item_PropertyChanged; } } break; case NotifyCollectionChangedAction.Remove: foreach (YourModel item in e.OldItems) { _filteredCollection.Remove(item); if (item is INotifyPropertyChanged notifyItem) { notifyItem.PropertyChanged -= Item_PropertyChanged; } } break; case NotifyCollectionChangedAction.Reset: _filteredCollection.Clear(); foreach (var item in _sourceCollection.Where(p => !p.deleted)) { _filteredCollection.Add(item); if (item is INotifyPropertyChanged notifyItem) { notifyItem.PropertyChanged += Item_PropertyChanged; } } break; } } private void Item_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == nameof(YourModel.deleted)) { var item = sender as YourModel; if (item.deleted && _filteredCollection.Contains(item)) { _filteredCollection.Remove(item); } else if (!item.deleted && !_filteredCollection.Contains(item)) { _filteredCollection.Add(item); } } }
该方案适合自定义逻辑较多的场景,但需注意内存泄漏问题,ViewModel销毁时要解绑相关事件。
内容的提问来源于stack exchange,提问作者Denis De Pauli
相关产品推荐
相关产品推荐

