C# 自定义可观察采集<;T>;或绑定列表<;T>;支持定期通知
摘要 我有一个快速变化的数据集,我希望将其绑定到UI(带有分组的Datagrid)。变化分为两个层次C# 自定义可观察采集<;T>;或绑定列表<;T>;支持定期通知,c#,wpf,observablecollection,large-data-volumes,bindinglist,C#,Wpf,Observablecollection,Large Data Volumes,Bindinglist,摘要 我有一个快速变化的数据集,我希望将其绑定到UI(带有分组的Datagrid)。变化分为两个层次 经常从集合中添加或删除项目(每种方式每秒500个) 每个项目有4个属性,在其生命周期内最多可更改5次 数据的特点如下: 藏品中约有5000件 一个项目可以在一秒钟内添加,然后进行5次属性更改,然后删除 项目也可能会在某个临时状态下保留一段时间,并应向用户显示 我遇到问题的关键需求 用户应该能够根据对象上的任何属性对数据集进行排序 我想做什么 仅每N秒更新一次UI 仅引发相关Noti
- 经常从集合中添加或删除项目(每种方式每秒500个)
- 每个项目有4个属性,在其生命周期内最多可更改5次
- 藏品中约有5000件
- 一个项目可以在一秒钟内添加,然后进行5次属性更改,然后删除李>
- 项目也可能会在某个临时状态下保留一段时间,并应向用户显示
- 用户应该能够根据对象上的任何属性对数据集进行排序
- 仅每N秒更新一次UI
- 仅引发相关NotifyPropertyChangedEvents
/// <summary>
/// A binding list which allows change events to be polled rather than pushed.
/// </summary>
[Serializable]
public class MonitoredBindingList<T> : BindingList<T>
{
private readonly object publishingLock = new object();
private readonly Queue<ListChangedEventArgs> addRemoveQueue;
private readonly LinkedList<HashSet<PropertyDescriptor>> changeList;
private readonly Dictionary<int, LinkedListNode<HashSet<PropertyDescriptor>>> changeListDict;
public MonitoredBindingList()
{
this.addRemoveQueue = new Queue<ListChangedEventArgs>();
this.changeList = new LinkedList<HashSet<PropertyDescriptor>>();
this.changeListDict = new Dictionary<int, LinkedListNode<HashSet<PropertyDescriptor>>>();
}
protected override void OnListChanged(ListChangedEventArgs e)
{
lock (publishingLock)
{
switch (e.ListChangedType)
{
case ListChangedType.ItemAdded:
if (e.NewIndex != Count - 1)
throw new ApplicationException("Items may only be added to the end of the list");
// Queue this event for notification
addRemoveQueue.Enqueue(e);
// Add an empty change node for the new entry
changeListDict[e.NewIndex] = changeList.AddLast(new HashSet<PropertyDescriptor>());
break;
case ListChangedType.ItemDeleted:
addRemoveQueue.Enqueue(e);
// Remove all changes for this item
changeList.Remove(changeListDict[e.NewIndex]);
for (int i = e.NewIndex; i < Count; i++)
{
changeListDict[i] = changeListDict[i + 1];
}
if (Count > 0)
changeListDict.Remove(Count);
break;
case ListChangedType.ItemChanged:
changeListDict[e.NewIndex].Value.Add(e.PropertyDescriptor);
break;
default:
base.OnListChanged(e);
break;
}
}
}
public void PublishChanges()
{
lock (publishingLock)
Publish();
}
internal void Publish()
{
while(addRemoveQueue.Count != 0)
{
base.OnListChanged(addRemoveQueue.Dequeue());
}
// The order of the entries in the changeList matches that of the items in 'this'
int i = 0;
foreach (var changesForItem in changeList)
{
foreach (var pd in changesForItem)
{
var lc = new ListChangedEventArgs(ListChangedType.ItemChanged, i, pd);
base.OnListChanged(lc);
}
i++;
}
}
}
//
///允许轮询而不是推送更改事件的绑定列表。
///
[可序列化]
公共类MonitoredBindingList:BindingList
{
私有只读对象publishingLock=新对象();
专用只读队列addRemoveQueue;
私有只读链接列表变更列表;
私有只读词典changeListDict;
公共监视绑定列表()
{
this.addRemoveQueue=新队列();
this.changeList=新建LinkedList();
this.changeListDict=新字典();
}
受保护的重写void OnListChanged(ListChangedEventArgs e)
{
锁(发布锁)
{
开关(如ListChangedType)
{
案例列表ChangedType.ItemAdded:
如果(e.NewIndex!=计数-1)
抛出新的ApplicationException(“项目只能添加到列表的末尾”);
//将此事件排队等待通知
addRemoveQueue.Enqueue(e);
//为新条目添加空的更改节点
changeListDict[e.NewIndex]=changeList.AddLast(newhashset());
打破
案例列表ChangedType.ItemDeleted:
addRemoveQueue.Enqueue(e);
//删除此项目的所有更改
changeList.Remove(changeListDict[e.NewIndex]);
for(int i=e.NewIndex;i0)
changeListDict.Remove(计数);
打破
案例ListChangedType.ItemChanged:
changeListDict[e.NewIndex].Value.Add(e.PropertyDescriptor);
打破
违约:
基数.唯一值(e);
打破
}
}
}
公共无效发布更改()
{
锁(发布锁)
发布();
}
内部作废发布()
{
while(addRemoveQueue.Count!=0)
{
base.OnListChanged(addRemoveQueue.Dequeue());
}
//变更列表中条目的顺序与'