locked
ObservableCollection.AddRange() RRS feed

  • Question

  • User482 posted

    If your Models expose an ObservableCollection, and you are adding lots of elements, you don't want this adding to fire a UI event every time.

    You can use this ObservableCollection which only notifies the UI to update after all the elements are updated when AddRange is used:

    public class ObservableCollectionFast<T> : ObservableCollection<T>
    {
        public ObservableCollectionFast()  : base()   {   }
    
        public ObservableCollectionFast(IEnumerable<T> collection)  : base(collection)   {    }
    
        public ObservableCollectionFast(List<T> list)   : base(list)  {        }
    
        public void AddRange(IEnumerable<T> range)
        {
            foreach (var item in range)
            {
                Items.Add(item);
            }
    
            this.OnPropertyChanged(new PropertyChangedEventArgs("Count"));
            this.OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
            this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }
    
        public void Reset(IEnumerable<T> range)
        {
            this.Items.Clear();
    
            AddRange(range);
        }
    }
    
    Wednesday, December 24, 2014 12:05 AM

All replies

  • User57783 posted

    Thanks alot for this, it solved a problem for me, I do not know why the ObservableCollection crashes when I used it directly. I will refer to the link where other people have the same problem, I hope that will solve it.

    Wednesday, January 14, 2015 7:39 PM
  • User392 posted

    I am surprised you send out a Reset action notification for AddRange. It is more accurate to do:

    this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add,range,startIndex));
    
    Thursday, October 29, 2015 5:30 PM
  • User28549 posted

    @IanVink, do you seen any red flags in adding the following method to the class? Collections are not my strong suit.

    ```csharp public void Update(IEnumerable range, IEqualityComparer comparer) { var newitems = range.ToList(); foreach (var add in newitems.Where(add => !Items.Contains(add, comparer))) { Items.Add(add); }

    for (var i = Items.Count - 1; i >= 0; i--)
    {
        if (!newitems.Contains(Items[i], comparer))
        {
            Items.RemoveAt(i);
        }
    }
    
    OnPropertyChanged(new PropertyChangedEventArgs("Count"));
    OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
    OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
    

    } ```

    Thursday, March 31, 2016 9:00 PM
  • User365327 posted

    I know this is an old post, but thanks Ian! Such a simple and elegant solution.

    Wednesday, February 7, 2018 2:54 PM
  • User7626 posted

    Since we now have C# 7, we can use this full-featured ObservableRangeCollection: https://gist.github.com/weitzhandler/65ac9113e31d12e697cb58cd92601091

    Thursday, March 22, 2018 4:56 PM
  • User221181 posted

    Thank you. Worked a treat.

    Wednesday, January 9, 2019 6:20 AM
  • User307736 posted

    Adding 5 more cents

            //---------------------------------------------------------------------------------------------------------
            public void InsertRange(int index, IEnumerable<T> collection)
            //---------------------------------------------------------------------------------------------------------
            {
                //NotifyCollectionChangedAction notificationMode = NotifyCollectionChangedAction.Add;
    
                CheckReentrancy();
    
                int currentIndex = index;
                var changedItems = collection is List<T> ? (List<T>)collection : new List<T>(collection);
                foreach (var i in changedItems)
                {
                    Items.Insert(currentIndex, i);
                    currentIndex++;
                }
                OnPropertyChanged(new PropertyChangedEventArgs("Count"));
                OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
                OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, changedItems, index));
            }
    
        //-----------------------------------------------------------------------------------------------------------
        public void ReportItemChange(T item)
        //-----------------------------------------------------------------------------------------------------------
        {
            NotifyCollectionChangedEventArgs args =
                new NotifyCollectionChangedEventArgs(
                    NotifyCollectionChangedAction.Replace,
                    item,
                    item,
                    IndexOf(item));
            OnCollectionChanged(args);
        }
    
    Wednesday, January 9, 2019 8:09 AM
  • User372994 posted

    Thank you Ian

    Tuesday, May 28, 2019 8:50 AM
  • User366747 posted

    Thank you, this help me solve some problems.

    Friday, June 7, 2019 8:53 PM