如何高效地从可观察集合中选择一个范围并放入另一个可观察集合中。

4

类似以下的伪代码:

ObservableCollection<TheClass> ob1 = new ObservableCollection<TheClass>();
ob1.Add(...);
ob1.Add(...); 
ob1.Add(...);
ob1.Add(...); 
ObservableCollection<TheClass> ob2;
ob2 = ob1.Range(0, 2);

考虑到这两个集合都可能包含大量数据。
谢谢。

1
使用这个构造函数怎么样:ob2 = new ObservableCollection<TheClass>(ob1.Take(2));?顺便说一下,数据的"量"应该不是什么问题,因为你只是在复制引用,对吧? - Corak
3个回答

5
ObservableCollection<TheClass> ob1 = new ObservableCollection<TheClass>();
ob1.Add(...);
ob1.Add(...); 
ob1.Add(...);
ob1.Add(...); 
ObservableCollection<TheClass> ob2;

// ob2 = ob1.Range(0, 2);
ob2 = new ObservableCollection(ob1.Skip(0).Take(2));

如果你坚持使用.Range方法,你可以自己编写一个扩展:

现在如果你真的坚持使用.Range方法,你可以自己编写一个扩展:
public static class ObservableCollectionExtensions
{
    public static ObservableCollection<T> Range(this ObservableCollection<T> sequence, int start, int count)
    {
         return new ObservableCollection(sequence.Skip(start).Take(count));
    }
}

现在你的代码应该可以编译了:
ObservableCollection<TheClass> ob1 = new ObservableCollection<TheClass>();
ob1.Add(...);
ob1.Add(...); 
ob1.Add(...);
ob1.Add(...); 
ObservableCollection<TheClass> ob2;

ob2 = ob1.Range(0, 2);

3

ObservableCollection 不支持 AddRange 方法。您可以编写一个扩展方法或创建一个继承自 ObservableCollection 类的新类来扩展 ObservableCollection 类的功能。例如:

public class ObservableRangeCollection<T> : ObservableCollection<T>
{
    public void AddRange(IEnumerable<T> collection)
    {
        var enumerable = collection as T[] ?? collection.ToArray();
        foreach (var item in enumerable)
        {
            Items.Add(item);
        }
        OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, enumerable.ToList()));
    }
}

你可以创建一个 ObservableRangeCollection 的实例来替代 ObservableCollection,并且对于 ob2 使用 AddRange 方法。然后使用 SkipTake 方法来获取你想要的范围,例如:

ObservableRangeCollection<TheClass> ob2 = new ObservableRangeCollection<TheClass>();
ob2.AddRange(ob1.Take(3));//Returns 3 number of contiguous elements from the start 
// Or to  grab a Range between 2 and 5
ob2.AddRange(ob1.Skip(2).Take(3)) 

1
@user2946329,你的答案是正确的。在看到你已经提供了答案并删除了我的回答之前,我自己也发布了相同的答案。这个问题怎么还在讨论呢? - Mark Feldman
@MarkFeldman,您指的是哪个答案?我已经看不到了。如果您不介意重新发布一下,我会很感激的。 - user2481095
@user2481095明确表示他已经删除了它,因此不再可用。那么这个被接受的答案呢? - Salah Akbari
这个答案对我不起作用。如果我尝试一次添加多个项目,我会得到一个“不支持范围操作”的异常。似乎唯一的解决方法是传递NotifyCollectionChangedAction.Reset。然而,我想被通知新添加的项目。我还没有找到实现这一点的方法。 - user2481095
@user2481095 根据他的问题,OP要求多个对象,而这个答案已经为他工作了,因为他已经接受了它。如果它对你不起作用,可能是你在这里漏掉了一些东西,正如我已经建议的那样,最好提出一个新问题,并在你的新问题中引用这个问题。 - Salah Akbari
显示剩余2条评论

1

在你保存扩展方法的任何地方使用它。

public static ObservableCollection<T> Range<T>(this ObservableCollection<T> oc, uint startIndex, uint length) => 
    oc.Skip(startIndex).Take(length);

并像这样使用它:
ob2 = ob1.Range(0, 2);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接