2

What I want to do is FreezableCollection.AddRange(collectionToAdd)

Each time I add to the FreezableCollection an event is raised and something happens. Now I have a new collection I would want to add but this time I want the CollectionChanged event of the FreezableCollection to fire only once.

Looping through and adding them will raise the event for each new item.

Is there a way I can add to FreezableCollection all at a goal, similar to List.AddRange?

adentum
  • 982
  • 1
  • 11
  • 21
  • I'm curious to know if my answer helps you. It seems to fit exactly what you're asking. – Bob Horn Mar 24 '12 at 21:46
  • Yes, it does fit what am asking, but I was hoping for a solution that wouldn't involve subclassing the collection. Maybe an extension method..., something that would work on the instance without changing the Collection type. thanks. – adentum Mar 24 '12 at 22:00
  • Well, the code is below. You could use it within extension methods. Instead of overrides, just use new (extension) method names. – Bob Horn Mar 24 '12 at 22:05
  • I don't see how I could implement this as an extension method, there are method overrides. How would you suppose I went about it? – adentum Mar 25 '12 at 00:27
  • Don't use overrides. Create new methods. These new methods would simply do what the overrides in the example do. – Bob Horn Mar 25 '12 at 16:58

2 Answers2

3

Derive from a collection and override the behavior that you'd like to change. I was able to do it this way:

public class PrestoObservableCollection<T> : ObservableCollection<T>
    {
        private bool _delayOnCollectionChangedNotification { get; set; }

        /// <summary>
        /// Add a range of IEnumerable items to the observable collection and optionally delay notification until the operation is complete.
        /// </summary>
        /// <param name="itemsToAdd"></param>
        public void AddRange(IEnumerable<T> itemsToAdd)
        {
            if (itemsToAdd == null) throw new ArgumentNullException("itemsToAdd");

            if (itemsToAdd.Any() == false) { return; }  // Nothing to add.

            _delayOnCollectionChangedNotification = true;            

            try
            {
                foreach (T item in itemsToAdd) { this.Add(item); }
            }
            finally
            {
                ResetNotificationAndFireChangedEvent();
            }
        }

        /// <summary>
        /// Clear the items in the ObservableCollection and optionally delay notification until the operation is complete.
        /// </summary>
        public void ClearItemsAndNotifyChangeOnlyWhenDone()
        {
            try
            {
                if (!this.Any()) { return; }  // Nothing available to remove.

                _delayOnCollectionChangedNotification = true;

                this.Clear();
            }
            finally
            {
                ResetNotificationAndFireChangedEvent();
            }
        }

        /// <summary>
        /// Override the virtual OnCollectionChanged() method on the ObservableCollection class.
        /// </summary>
        /// <param name="e">Event arguments</param>
        protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
        {
            if (_delayOnCollectionChangedNotification) { return; }

            base.OnCollectionChanged(e);
        }

        private void ResetNotificationAndFireChangedEvent()
        {
            // Turn delay notification off and call the OnCollectionChanged() method and tell it we had a change in the collection.
            _delayOnCollectionChangedNotification = false;
            this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }
    }
Bob Horn
  • 33,387
  • 34
  • 113
  • 219
  • This is a nice example for `ObservableCollection`, but `FreezableCollection` don't expose `OnCollectionChanged`. I still cannot suppress change notification for FreezableCollections. – adentum Mar 25 '12 at 00:58
  • 1
    Sorry adentum, I didn't realize that FreezableCollection was a .NET class. I was thinking it was something you were creating. So, no, I don't have the answer for you. However, I'm hoping that the general idea here can still apply. – Bob Horn Mar 25 '12 at 01:11
0

To follow up @BobHorn's nice answer, to make it works with FreezableCollection,

from document:

This member is an explicit interface member implementation. It can be used only when the FreezableCollection instance is cast to an INotifyCollectionChanged interface.

So you can do that with a cast.

(FreezableCollection as INotifyCollectionChanged).CollectionChanged += OnCollectionChanged;
Val
  • 21,938
  • 10
  • 68
  • 86