When Clearing an ObservableCollection, There are No Items in e.OldItems

前端 未结 20 1772
不知归路
不知归路 2020-11-30 00:27

I have something here that is really catching me off guard.

I have an ObservableCollection of T that is filled with items. I also have an event handler attached to t

20条回答
  •  一生所求
    2020-11-30 00:45

    I tackled this one in a slightly different manner as I wanted to register to one event and handle all additions and removals in the event handler. I started off overriding the collection changed event and redirecting reset actions to removal actions with a list of items. This all went wrong as I was using the observable collection as an items source for a collection view and got "Range actions not supported".

    I finally created a new event called CollectionChangedRange which acts in the manner I expected the inbuilt version to act.

    I can't imagine why this limitation would be allowed and hope that this post at least stops others from going down the dead end that I did.

    /// 
    /// An observable collection with support for addrange and clear
    /// 
    /// 
    [Serializable]
    [TypeConverter(typeof(ExpandableObjectConverter))]
    public class ObservableCollectionRange : ObservableCollection
    {
        private bool _addingRange;
    
        [field: NonSerialized]
        public event NotifyCollectionChangedEventHandler CollectionChangedRange;
    
        protected virtual void OnCollectionChangedRange(NotifyCollectionChangedEventArgs e)
        {
            if ((CollectionChangedRange == null) || _addingRange) return;
            using (BlockReentrancy())
            {
                CollectionChangedRange(this, e);
            }
        }
    
        public void AddRange(IEnumerable collection)
        {
            CheckReentrancy();
            var newItems = new List();
            if ((collection == null) || (Items == null)) return;
            using (var enumerator = collection.GetEnumerator())
            {
                while (enumerator.MoveNext())
                {
                    _addingRange = true;
                    Add(enumerator.Current);
                    _addingRange = false;
                    newItems.Add(enumerator.Current);
                }
            }
            OnCollectionChangedRange(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, newItems));
        }
    
        protected override void ClearItems()
        {
            CheckReentrancy();
            var oldItems = new List(this);
            base.ClearItems();
            OnCollectionChangedRange(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, oldItems));
        }
    
        protected override void InsertItem(int index, T item)
        {
            CheckReentrancy();
            base.InsertItem(index, item);
            OnCollectionChangedRange(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index));
        }
    
        protected override void MoveItem(int oldIndex, int newIndex)
        {
            CheckReentrancy();
            var item = base[oldIndex];
            base.MoveItem(oldIndex, newIndex);
            OnCollectionChangedRange(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Move, item, newIndex, oldIndex));
        }
    
        protected override void RemoveItem(int index)
        {
            CheckReentrancy();
            var item = base[index];
            base.RemoveItem(index);
            OnCollectionChangedRange(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index));
        }
    
        protected override void SetItem(int index, T item)
        {
            CheckReentrancy();
            var oldItem = base[index];
            base.SetItem(index, item);
            OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, oldItem, item, index));
        }
    }
    
    /// 
    /// A read only observable collection with support for addrange and clear
    /// 
    /// 
    [Serializable]
    [TypeConverter(typeof(ExpandableObjectConverter))]
    public class ReadOnlyObservableCollectionRange : ReadOnlyObservableCollection
    {
        [field: NonSerialized]
        public event NotifyCollectionChangedEventHandler CollectionChangedRange;
    
        public ReadOnlyObservableCollectionRange(ObservableCollectionRange list) : base(list)
        {
            list.CollectionChangedRange += HandleCollectionChangedRange;
        }
    
        private void HandleCollectionChangedRange(object sender, NotifyCollectionChangedEventArgs e)
        {
            OnCollectionChangedRange(e);
        }
    
        protected virtual void OnCollectionChangedRange(NotifyCollectionChangedEventArgs args)
        {
            if (CollectionChangedRange != null)
            {
                CollectionChangedRange(this, args);
            }
        }
    
    }
    

提交回复
热议问题