.NET 可观察字典
我编写了以下类,它实现(或尝试!)带有通知的字典:
public partial class ObservableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, INotifyCollectionChanged
{
public ObservableDictionary() : base() { }
public ObservableDictionary(int capacity) : base(capacity) { }
public ObservableDictionary(IEqualityComparer<TKey> comparer) : base(comparer) { }
public ObservableDictionary(IDictionary<TKey, TValue> dictionary) : base(dictionary) { }
public ObservableDictionary(int capacity, IEqualityComparer<TKey> comparer) : base(capacity, comparer) { }
public ObservableDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer) : base(dictionary, comparer) { }
public event NotifyCollectionChangedEventHandler CollectionChanged;
public new TValue this[TKey key]
{
get
{
return base[key];
}
set
{
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, key, 0));
base[key] = value;
}
}
public new void Add(TKey key, TValue value)
{
base.Add(key, value);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, key, 0));
}
public new bool Remove(TKey key)
{
bool x = base.Remove(key);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, key, 0));
return x;
}
public new void Clear()
{
base.Clear();
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (CollectionChanged != null)
{
CollectionChanged(this, e);
}
}
}
在另一个类中,我有一个 MyObservableDictionary.CollectionChanged
事件的侦听器:
我遇到的问题是事件不会触发。我该如何解决这个问题?
I have written the following class which implements(or tries to!) a dictionary with notifications:
public partial class ObservableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, INotifyCollectionChanged
{
public ObservableDictionary() : base() { }
public ObservableDictionary(int capacity) : base(capacity) { }
public ObservableDictionary(IEqualityComparer<TKey> comparer) : base(comparer) { }
public ObservableDictionary(IDictionary<TKey, TValue> dictionary) : base(dictionary) { }
public ObservableDictionary(int capacity, IEqualityComparer<TKey> comparer) : base(capacity, comparer) { }
public ObservableDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer) : base(dictionary, comparer) { }
public event NotifyCollectionChangedEventHandler CollectionChanged;
public new TValue this[TKey key]
{
get
{
return base[key];
}
set
{
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, key, 0));
base[key] = value;
}
}
public new void Add(TKey key, TValue value)
{
base.Add(key, value);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, key, 0));
}
public new bool Remove(TKey key)
{
bool x = base.Remove(key);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, key, 0));
return x;
}
public new void Clear()
{
base.Clear();
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (CollectionChanged != null)
{
CollectionChanged(this, e);
}
}
}
In another class, I have a listener for the MyObservableDictionary.CollectionChanged
event:
The problem I'm having is that the event doesn't fire. How can I fix this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
Microsoft ParallelExtensionsExtras 提供的此类不仅是可观察的,而且是并发的:
现在可以通过 Nuget 获得:
https://www.nuget.org/packages/MSFT.ParallelExtensionsExtras/
源代码最近针对 .NET Standard 进行了更新2.1 于 05/11/2020 发布,源代码可在 GitHub 上获取:
https://github.com/dotnet/samples/tree/master/csharp /parallel/ParallelExtensionsExtras
请注意,某些功能现在已成为较新的 .NET 框架的一部分。
ParallelExtensions“额外功能”仍然有价值吗?
Microsoft Tour 博客:
https://blogs.msdn.microsoft。 com/pfxteam/2010/04/04/a-tour-of-parallelextensionsextras/
The Microsoft ParallelExtensionsExtras provides this class which is not only observable but is also concurrent:
Now available via Nuget:
https://www.nuget.org/packages/MSFT.ParallelExtensionsExtras/
The source code was recently updated for .NET Standard 2.1 on 05/11/2020 and the source code is available at GitHub:
https://github.com/dotnet/samples/tree/master/csharp/parallel/ParallelExtensionsExtras
Note that some of the features are now a part of newer .NET frameworks.
Are the ParallelExtensions "Extras" still of value?
Microsoft Tour Blog:
https://blogs.msdn.microsoft.com/pfxteam/2010/04/04/a-tour-of-parallelextensionsextras/
我建议您实现
IDictionary
而不是继承自Dictionary
。由于您必须使用new
而不是override
,因此这些方法可能只是在基类而不是您的类上调用。我很想在内部使用Dictionary
来实际存储数据。事实上我发现了这个:
http://博客。 microsoft.co.il/blogs/shimmy/archive/2010/12/26/observabledictionary-lt-tkey-tvalue-gt-c.aspx
I'd suggest that you implement the
IDictionary<TKey, TValue>
instead of inheriting fromDictionary<TKey, TValue>
. Since you have to usenew
rather thanoverride
it's possible that the methods are simply being called on the base class rather than your class. I'd be tempted to use aDictionary<TKey, TValue>
internally to do the actual storing of data.In fact I found this:
http://blogs.microsoft.co.il/blogs/shimmy/archive/2010/12/26/observabledictionary-lt-tkey-tvalue-gt-c.aspx
您的解决方案 - 已修复;)
Your solution - Fixed ;)
我推出了自己的:
https://www.nuget.org/packages/hellosam.net.collections/
它使用 AVL 树,因此操作是 O(log N),而我见过的使用 List.indexOf() 的大多数实现都是 O(N)。
它甚至可以观察您的项目 INotifyPropertyChanged 并将它们转换为可观察的集合事件,以便保持 DataGrid 排序/组对更改的响应。
I rolled out my own:
https://www.nuget.org/packages/hellosam.net.collections/
It uses AVL tree so operations are O(log N) instead, where most implementations I have seen using List.indexOf() are O(N).
It can even observe your item INotifyPropertyChanged and convert them to a observable collection event, so to keep the DataGrid sort/group response to the change.
正如 Ignatio 和 Matthew 在 this 答案中指出的那样,仅引发
Reset
集合更改通知是不正确的,如果调用者需要知道实际发生了什么变化,则不是很有用。幸运的是,它很容易纠正。请注意,此版本使用Send
而不是 Nathan 在之前的答案中提到的Post
,因为 WPF 对删除时报告正确的索引很敏感,如果错误,则会产生 这个令人困惑的异常。 (买者自负:如果存在许多重叠的更改,我仍然不完全相信报告的索引将完全可靠,特别是考虑到字典应被视为无序。)As Ignatio and Matthew pointed out in this answer, only raising the
Reset
collection change notification is incorrect, and not very useful if the caller needs to know what actually changed. Fortunately it is easily corrected. Note this version usesSend
instead ofPost
as Nathan mentioned in the earlier answer, because WPF is sensitive to reporting back the correct index upon removal, and getting it wrong yields this confusing exception. (Caveat emptor: I'm still not completely convinced the reported index will be fully reliable if there are many overlapping changes, especially given that Dictionaries should be treated as un-ordered.)我设法找到了一个解决方案 - 解决方法,
但我不再实现 INotifyCollectionChanged 接口。
I have managed to find a solution - workaround
I've no longer implement the
INotifyCollectionChanged
interface though.