Skip to content

MVVM 中 ICollectionView 与 ObservableCollection

约 654 字大约 2 分钟

WPF

2025-12-11

ObservableCollection

public class ObservableCollection<T> : Collection<T>, INotifyCollectionChanged, INotifyPropertyChanged

负责数据本身的变化通知(增、删、改)

  • 实现了 INotifyCollectionChangedINotifyPropertyChanged
  • 当向其中 添加、删除或替换元素 时,会自动通知绑定的 UI 更新。
  • 关注的是“数据内容”的变化
  • 是一个具体的集合实现(类似 List<T> 的增强版)。

ICollectionView

是一个视图接口,包装已有的集合 比如ObservableCollection。不会修改原始集合,只是“怎么展示”的逻辑。

  • 提供:
    • Filter(自定义筛选逻辑)
    • SortDescriptions(排序规则)
    • GroupDescriptions(分组)
    • CurrentItem(当前选中项)
  • WPF 控件(如 DataGrid)在绑定集合时,内部会自动创建一个默认的 ICollectionView
var source = new ObservableCollection<Person>();
// ... 添加数据


ICollectionView view = CollectionViewSource.GetDefaultView(source);
view.Filter = o => (o as Person)?.Age >= 18; // 只显示成年人
// 原始 source 未变,但 UI 只显示满足条件的项

结合使用

// ViewModel
private ObservableCollection<Order> _allOrders = new();
public ICollectionView OrdersView { get; }

public MyViewModel()
{
    // 加载所有订单(原始数据)
    LoadOrders(); // 填充 _allOrders

    // 创建视图
    OrdersView = CollectionViewSource.GetDefaultView(_allOrders);

    // 设置展示逻辑
    OrdersView.Filter = FilterOrder;
}

private bool FilterOrder(object item) => (item as Order)?.Status == "Pending";

一个很典型的场景,一个总的数据源,需要根据状态显示到不同的子页面上

ViewModelBase.cs
//总数据源
public class ScanViewModelBase : ViewModelBase
{
    /// <summary>
    /// 扫描数据服务(单例,用于共享玻片信息)
    /// </summary>
    protected readonly ScanDataService _ScanDataService;

    /// <summary>
    /// 信息集合(从共享服务获取,切换页面不会被重新初始化)
    /// </summary>
    public ObservableCollection<SlideInfo> SildeInfos => _ScanDataService.SildeInfos;


    public ScanViewModelBase(IContainerProvider containerProvider) : base(containerProvider)
    {
        _ScanDataService = containerProvider.Resolve<ScanDataService>();
    }
    
    // 每个子类实现自己的过滤器
	public virtual bool SlideFilter(object slides) => true;
	
	private ICollectionView? _filteredView;
	protected ICollectionView CreateFilteredView()
	{
	    if (_filteredView != null) return _filteredView;
	
	    var view = new ListCollectionView(_ScanDataService.SildeInfos);
	    view.Filter = SlideFilter;
	    _filteredView = view;
	    return view;
	}
}

总结

特性ObservableCollection<T>ICollectionView
类型具体集合类接口(视图)
职责管理数据本身管理数据展示方式
通知机制自动通知增删改不直接通知,但依赖底层集合的通知
支持筛选/排序
是否修改原始数据✅(本身是数据源)❌(只提供视图)
通常用在ViewModel 的数据字段ViewModel 的绑定属性(供 View 使用)