将IList中的元素添加到ObservableCollection中

30

我有一个ObservableCollection,我想将一个IList的内容设置为这个集合。现在,我可以只创建一个新的集合实例...:

public ObservableCollection<Bar> obs = new ObservableCollection<Bar>(); 
public void Foo(IList<Bar> list)
{
    obs = new ObservableCollection<Bar>(list); 
}

但我该如何将 IList 的内容添加到我的现有 ObservableCollection 中呢?我必须循环遍历所有元素吗,还是有更好的方法?

public void Foo(IList<Bar> list)
{
   foreach (var elm in list)
       obs.Add(elm); 
}
6个回答

61

如何将IList的内容添加到现有的ObservableCollection中?我必须遍历所有元素吗,还是有更好的方法?

虽然可能存在一些“更好”的方法,涉及使用第三方依赖项、一些低级别的操作等。但是,循环遍历集合是可以的并且有效。我建议这样做。简而言之,没有“更好”的方法。

这是此答案的旧版本,它错误地使用了LINQ(潜在地迭代集合两次,只为了节省一两行代码)。我想删除整个答案,但我不能这样做,因为它是被接受的答案。

你可以这样做:

public void Foo(IList<Bar> list) =>
    list.ToList().ForEach(obs.Add);

或者作为扩展方法,

public static void AddRange<T>(
    this ObservableCollection<T> collection, IEnumerable<T> items) =>
    items.ToList().ForEach(collection.Add);

3
@Richard - 虽然这是真的,但在内部它执行了 new List<T>(list) - 它内部调用 ((ICollection<T>)list).CopyTo(T[]),而在大多数 IList<T> 的实现中(例如 List<T>)会调用一个本地(外部)数组复制函数。 这应该非常高效,只涉及必要引用的原子复制,而不是成员迭代。 - Adam Ralph
在 Prism 4 中,它是 CollectionExtensions.AddRange<T>(http://msdn.microsoft.com/en-us/library/gg405741(v=pandp.40).aspx)。 - Neo
你可以避免使用ToList()。如果你这样做,我将执行2个操作。一个是转换为列表的循环,另一个是添加的循环。IList继承自IEnumerator,所以你只需要使用list.ForEach(obs.Add);即可。 - Sergio Escudero
1
@SergioEscudero 不行,你不能这样做 - https://dotnetfiddle.net/7nbPiK - Adam Ralph
1
话虽如此,这个(12岁的)答案确实滥用了LINQ,所以我要编辑它。我不能删除它,因为它是被接受的答案。 - Adam Ralph
显示剩余2条评论

12

如果你使用 C#3+,你可以编写自己的扩展方法来帮助你解决这个问题。以下代码经过了一些基本测试以确保它能够正常工作:

public static void AddRange<T>(this ObservableCollection<T> coll, IEnumerable<T> items)
{
    foreach (var item in items)
    {
        coll.Add(item);
    }
}

1
微软针对WPF项目的Prism包含类似的扩展方法(尽管它们的版本返回集合而不是void,以支持方法链接)。只需引用Microsoft.Practices.Composite.dll并添加using Microsoft.Practices.Composite;即可。 - totorocat
每次添加一个项目时,都会触发一个事件。如果你想要等待并在最后触发通知,你需要像这样的东西:https://stackoverflow.com/questions/13302933/how-to-avoid-firing-observablecollection-collectionchanged-multiple-times-when-r - undefined

1
循环是唯一的方法,因为对于ObservableCollection没有AddRange等效方法。

0

0

0
如果您想要实例化一个可观察的集合,并且想要将新的范围添加到可观察的集合中,您可以尝试以下方法:
var list = new List<Utilities.T>();
            list.AddRange(order.ItemTransactions.ToShortTrans());
            list.AddRange(order.DealTransactions.ToShortTrans());
            ShortTransactions = new ObservableCollection<T>(list);

通过这种方式,您可以将范围添加到ObservableCollection中,而无需循环。


你刚刚清除了所有订阅通知变更事件的订阅者。 - undefined

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