正在考虑System.Collections.ObjectModel ObservableCollection<T>类。这个很奇怪,因为
-
它有一个只需要一项的添加方法。没有AddRange或等效项。
-
Notification事件参数具有NewItems属性,该属性是一个IList(对象的..不是T)
我这里需要将一批对象添加到集合中,并且侦听器还将批处理作为通知的一部分。我是否缺少ObservableCollection的东西?还有另一个符合我要求的课程吗?
更新:不想自己动手。我必须构建添加/删除/更改等。很多东西。
相关问题:
https://stackoverflow.com/questions/670577/observablecollection-doesnt-support-addrange-method-so-i-get-notified-for-each
似乎INotifyCollectionChanged接口允许在添加多个项目时进行更新,所以我不确定为什么ObservableCollection<T>没有AddRange。您可以为AddRange设置扩展方法,但这将为添加的每个项目导致一个事件。如果那是不可接受的,则您应该能够从ObservableCollection<T>继承,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| 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);
}
} |
这个想法和fryguybob的想法是一样的-有点奇怪,ObservableCollection是半完成的。这个东西的事件args甚至都没有使用Generics ..让我使用IList(就是这样。..昨天:)
经过测试的代码段如下...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| 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);
}
}
} |
如果您使用上述任何一种发送添加范围命令并将observablecolletion绑定到listview的实现,都会收到此讨厌的错误。
1 2 3 4 5
| 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) |
我使用的实现使用Reset事件,该事件在WPF框架周围更加均匀地实现:
1 2 3 4 5 6 7
| public void AddRange(IEnumerable< T > collection)
{
foreach (var i in collection) Items.Add(i);
OnPropertyChanged("Count");
OnPropertyChanged("Item[]");
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
} |
System.Collections.ObjectModel.Collection<T>不仅是一个不错的选择,而且在帮助文档中,有一个示例说明如何重写其各种受保护的方法以获取通知。 (向下滚动到示例2。)
我已经多次看到这种问题,我想知道为什么连微软都在其他地方已经推广了更好的collection的地方推广ObservableCollection。
BindingList< T >
这允许您关闭通知并执行批量操作,然后打开通知。
另一个类似于CollectionView模式的解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| 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
}
} |
如果您想从某种集合中继承,最好从System.Collections.ObjectModel.Collection继承,因为它提供了用于重写的虚拟方法。如果走那条路线,您将不得不遮蔽List之外的方法。
我不知道任何提供此功能的内置集合,但我欢迎对此进行纠正:)
从List < T >继承并重写Add()和AddRange()方法引发事件吗?
要快速添加,可以使用:
1
| ((List<Person>)this.Items).AddRange(NewItems); |
使用C#和VB中的AddRange,RemoveRange和Replace range方法查看Observable集合。
在VB中:INotifyCollectionChanging实现。