ObservableCollection使用Clear时CollectionChanged内e.OldItems中为null

文章讲述了在WPF开发中,如何处理ObservableCollection的Clear操作导致的Undo/Redo功能失效问题,提出了自定义继承和使用扩展方法两种解决方案。
摘要由CSDN通过智能技术生成

在WPF日常开发中,经常会用到ObservableCollection进行数据源绑定,并且使用+=CollectionChanged事件来监控Add或Remove元素时数据集合的变化。

最近在开发需求时,牵扯到了历史功能undo redo,当ObservableCollection发生变化了,为了能够撤销恢复,在CollectionChanged事件中捕捉e.OldItems,并将它加入到undo/redo队列:

public ObservableCollection<Info> Infos { get; } = new ObservableCollection<Info>();

// ...

private void InfosOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
	//...
	DefaultChangeFactory.Current.OnCollectionChanged(this, "Infos", e.OldItems);
}

一直也没啥事,直到调用了

Infos.Clear();

发现调用Clear时InfosOnCollectionChanged中e.OldItems为null,无法将历史Infos内的数据进行保存。
网上搜了搜,根据资料显示,Clear时发出的是Reset动作,此时CollectionChanged不携带任何历史数据,.Net设计如此。
既然如此,那就只能想办法规避,两种方案:
一是自定义类继承自ObservableCollection,实现其内部虚函数ClearItems(),如下:

public class NewObservableCollection<T> : ObservableCollection<T>
{
    protected override void ClearItems()
    {
        List<T> removedList = new List<T>(this); //先缓存历史数据
        base.ClearItems(); //再clear all
        base.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, removedList)); //最后把缓存的数据通过事件参数发出去
    }    
	//重载事件处理
    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        if (e.Action != NotifyCollectionChangedAction.Reset)
            base.OnCollectionChanged(e);
    }
    // Constructors omitted
    ...
}

二是定义扩展方法,添加新方法进行调用:

public static void RemoveAll(this IList list)
{
   while (list.Count > 0)
   {
      list.RemoveAt(list.Count - 1);
   }
}

此方案最简单,代码量也最小。

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值