正在考虑System.Collections.ObjectModel ObservableCollection<T>
课程。这个很奇怪,因为
我的需要是将一批对象添加到集合中,并且侦听器还将批处理作为通知的一部分。我错过了ObservableCollection的东西吗?还有其他课程符合我的规范吗?
更新:尽量不要自己动手。我必须构建添加/删除/更改等等。很多东西。
答案 0 :(得分:19)
似乎INotifyCollectionChanged
界面允许在添加多个项目时进行更新,因此我不确定为什么ObservableCollection<T>
没有AddRange
。您可以为AddRange
创建一个扩展方法,但这会导致添加的每个项目都有一个事件。如果这是不可接受的,您应该能够继承ObservableCollection<T>
,如下所示:
public class MyObservableCollection<T> : ObservableCollection<T>
{
// matching constructors ...
bool isInAddRange = false;
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
// intercept this when it gets called inside the AddRange method.
if (!isInAddRange)
base.OnCollectionChanged(e);
}
public void AddRange(IEnumerable<T> items)
{
isInAddRange = true;
foreach (T item in items)
Add(item);
isInAddRange = false;
var e = new NotifyCollectionChangedEventArgs(
NotifyCollectionChangedAction.Add,
items.ToList());
base.OnCollectionChanged(e);
}
}
答案 1 :(得分:6)
这个想法与fryguybob的想法相同 - 有点奇怪,ObservableCollection有点半完成。这件事的事件args甚至没有使用Generics ..让我使用IList(就是这样......昨天:) 经过测试的代码片段如下......
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
namespace MyNamespace
{
public class ObservableCollectionWithBatchUpdates<T> : ObservableCollection<T>
{
public void AddRange(ICollection<T> obNewItems)
{
IList<T> obAddedItems = new List<T>();
foreach (T obItem in obNewItems)
{
Items.Add(obItem);
obAddedItems.Add(obItem);
}
NotifyCollectionChangedEventArgs obEvtArgs = new NotifyCollectionChangedEventArgs(
NotifyCollectionChangedAction.Add,
obAddedItems as System.Collections.IList);
base.OnCollectionChanged(obEvtArgs);
}
}
}
答案 2 :(得分:4)
System.Collections.ObjectModel.Collection<T>
不仅是一个不错的选择,而且在帮助文档中还有an example如何覆盖其各种受保护的方法以获取通知。 (向下滚动到示例2。)
答案 3 :(得分:4)
如果您使用上述任何发送add range命令并将observablecolletion绑定到listview的实现,您将收到这个令人讨厌的错误。
NotSupportedException at System.Windows.Data.ListCollectionView.ValidateCollectionChangedEventArgs(NotifyCollectionChangedEventArgs e) at System.Windows.Data.ListCollectionView.ProcessCollectionChanged(NotifyCollectionChangedEventArgs args) at System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e) at System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
我使用的实现使用了围绕WPF框架更均匀实现的Reset事件:
public void AddRange(IEnumerable<T> collection)
{
foreach (var i in collection) Items.Add(i);
OnPropertyChanged("Count");
OnPropertyChanged("Item[]");
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
答案 4 :(得分:3)
我已经多次看过这样的问题了,我想知道为什么即使微软也在其他任何地方推广ObservableCollection已经有了更好的收藏......
BindingList<T>
允许您关闭通知并执行批量操作,然后启用通知。
答案 5 :(得分:2)
如果您想要从某种类型的集合继承,那么最好继承System.Collections.ObjectModel.Collection,因为它提供了覆盖的虚方法。如果你走这条路,你将不得不从List中隐藏方法。
我不知道任何提供此功能的内置集合,但我欢迎更正:)
答案 6 :(得分:2)
另一种类似于CollectionView模式的解决方案:
public class DeferableObservableCollection<T> : ObservableCollection<T>
{
private int deferLevel;
private class DeferHelper<T> : IDisposable
{
private DeferableObservableCollection<T> owningCollection;
public DeferHelper(DeferableObservableCollection<T> owningCollection)
{
this.owningCollection = owningCollection;
}
public void Dispose()
{
owningCollection.EndDefer();
}
}
private void EndDefer()
{
if (--deferLevel <= 0)
{
deferLevel = 0;
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
public IDisposable DeferNotifications()
{
deferLevel++;
return new DeferHelper<T>(this);
}
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (deferLevel == 0) // Not in a defer just send events as normally
{
base.OnCollectionChanged(e);
} // Else notify on EndDefer
}
}
答案 7 :(得分:1)
继承自List&lt; T&gt;并覆盖Add()和AddRange()方法来引发事件?
答案 8 :(得分:0)
在C#和VB中查看Observable collection with AddRange, RemoveRange and Replace range methods。
在VB中:INotifyCollectionChanging实现。
答案 9 :(得分:0)
如需快速添加,您可以使用:
((List<Person>)this.Items).AddRange(NewItems);
答案 10 :(得分:-1)
扩展方法人员救援!
/// <summary>
/// Adds all given items to the collection
/// </summary>
/// <param name="collection">The collection.</param>
/// <param name="toAdd">Objects to add.</param>
public static void AddAll<T>(this IList<T> collection, params T[] toAdd)
{
foreach (var o in toAdd)
collection.Add(o);
}