在ObservableCollection上实现AddRange,并对DataBinding提供适当的支持

时间:2013-01-29 20:58:18

标签: c# data-binding windows-phone-8 observablecollection addrange

我希望自己的ObservableCollection后代支持AddRange方法。 这是我现在拥有的:

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);
    }
}

我对这里发生的事情并不了解,为什么会引发这些事件。这是我在对google和stackoverflow进行一些研究后组装的一个解决方案。

现在,如果我将我的班级的一个实例绑定到LongListSelector,那么在通过InsertRangeObservableCollectionPlus动态添加项目之后,绑定LongListSelector的滚动位置发送到它的顶部。

如果我以这种标准方式添加项目:foreach (var item in items) collection.Add(item);那么LongListSelector的位置不会移位。但是当然这样我得到的DataBinding通知开销是不受欢迎的。

显然,我当前的解决方案出了问题。如何实现InsertRange,其行为与foreach (var item in items) collection.Add(item);完全相同,但只会触发一次DataBinding通知,并且不会对绑定对象的滚动位置做出奇怪的事情?

4 个答案:

答案 0 :(得分:3)

可能是因为您发送了NotifyCollectionChangedAction.Reset通知,可能只是NotifyCollectionChangedAction.Add会有效,可能是:)

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()));
    }
}

答案 1 :(得分:2)

我最近在一个项目中使用过这个......

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 :(得分:0)

您在使用DataBinding时遇到的问题可能与以下事实有关:您没有在ObservableCollection according to the source code中引发索引器(属性名称“ Item []”)的PropertyChanged。

您还可以查看James Montemagno here on GitHub ObservableRangeCollection 的一个很好的实现,它继承自 ObservableColection ,并包含 AddRange ReplaceRange 方法,以及数据绑定所需的所有PropertyChaged和CollectionChanged通知。

答案 3 :(得分:-1)

花了我很多年,麻烦始终是传递给NotifyCollectionChangedEventArgs ctor的参数。  根据行动,有许多不同的ctors采取不同的论点。以下似乎最终对我有用: https://github.com/lolluslollus/Utilz/blob/master/Utilz/SwitchableObservableCollection.cs