Implement AddRange on ObservableCollection with proper DataBinding support

I would like my own descendant to ObservableCollection

support the method AddRange

. Here's what I have now:

public class ObservableCollectionPlus<T> : ObservableCollection<T>
{
    public void InsertRange(IEnumerable<T> items)
    {
        this.CheckReentrancy();
        foreach (var item in items) Items.Add(item);

        var type = NotifyCollectionChangedAction.Reset;
        var colChanged = new NotifyCollectionChangedEventArgs(type);
        var countChanged = new PropertyChangedEventArgs("Count");

        OnPropertyChanged(countChanged);
        OnCollectionChanged(colChanged);
    }
}

      

I don't know very well what exactly is happening here and why these events occur. This is a solutiom I put together after some research on google and stackoverflow.

Now if I bind an instance of my class to say LongListSelector

, then after dynamically adding items through InsertRange

to ObservableCollectionPlus

, the anchored scroll position is LongListSelector

sent to it from the top.

If I add items in the standard way: foreach (var item in items) collection.Add(item);

then the position is LongListSelector

not shifted. But, of course, this way I get the overhead with the DataBinding notification, in which this is not desired.

Apparently there is something wrong with my current solution. How can I implement InsertRange

that will behave exactly like foreach (var item in items) collection.Add(item);

but will only send a DataBinding notification once and won't do weird things to bind the scroll position of the object?

+3


source to share


3 answers


It might be because you send a notification NotifyCollectionChangedAction.Reset

, it might just NotifyCollectionChangedAction.Add

work, maybe :)



public class ObservableRangeCollection<T> : ObservableCollection<T>
{
    public void AddRange(IEnumerable<T> collection)
    {
        foreach (var i in collection)
        {
            Items.Add(i);
        }
        OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, collection.ToList()));
    }
}

      

+3


source


I recently used this on a project ...



public class RangeObservableCollection<T> : ObservableCollection<T>
{
    private bool _suppressNotification = false;

    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        if (!_suppressNotification)
            base.OnCollectionChanged(e);
    }

    public void AddRange(IEnumerable<T> list)
    {
        if (list == null)
            throw new ArgumentNullException("list");

        _suppressNotification = true;

        foreach (T item in list)
        {
            Add(item);
        }
        _suppressNotification = false;
        OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
    }
}

      

+2


source


It took me ages, the problem was always that the arguments were being passed to the NotifyCollectionChangedEventArgs ctor. Depending on the action, there are many different factors that take different arguments. Seems like it finally works for me: https://github.com/lolluslollus/Utilz/blob/master/Utilz/SwitchableObservableCollection.cs

-1


source







All Articles