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

问题描述 投票:3回答:4

我想我自己的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然后,在通过InsertRange动态添加项目到ObservableCollectionPlus之后,绑定的LongListSelector的滚动位置被发送到它的顶部。

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

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

c# data-binding windows-phone-8 observablecollection addrange
4个回答
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()));
    }
}

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

0
投票

您在使用DataBinding时遇到的问题可能与您没有为Indexer(属性名称“Item []”)引发PropertyChanged这一事实有关,因为它发生在ObservableCollection according to the source code中。

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


-1
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.