首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在没有索引的集合上实现INotifyCollectionChanged

在没有索引的集合上实现INotifyCollectionChanged
EN

Stack Overflow用户
提问于 2011-06-07 00:56:27
回答 4查看 12K关注 0票数 15

我现在只是在ASP.Net工作了几年后,才接触到WPF的脚趾。我目前正在努力解决的问题是,我有一个自定义的集合类,我需要将它绑定到一个列表框。除了从集合中移除一项之外,一切似乎都正常。当我尝试这样做时,我得到了错误:“Collection Remove event must specify item position.”,问题是这个集合没有使用索引,所以我看不到指定位置的方法,而且到目前为止,谷歌还没有向我展示一个可行的解决方案…

该类被定义为实现ICollection<>INotifyCollectionChanged。我的内部项容器是一个Dictionary,它使用项的名称(字符串)值作为键。除了这两个接口定义的方法之外,这个集合还有一个索引器,允许按名称访问项,并重写ContainsRemove方法,以便也可以使用项名称调用它们。这适用于添加和编辑,但当我尝试删除时抛出上述异常。

以下是相关代码的摘录:

代码语言:javascript
复制
class Foo
{
    public string Name
    {
        get;
        set;
    }
}
class FooCollection : ICollection<Foo>, INotifyCollectionChanged
{
    Dictionary<string, Foo> Items;

    public FooCollection()
    {
        Items = new Dictionary<string, Foo>();
    }

    #region ICollection<Foo> Members

    //***REMOVED FOR BREVITY***

    public bool Remove(Foo item)
    {
        return this.Remove(item.Name);
    }
    public bool Remove(string name)
    {
        bool Value = this.Contains(name);
        if (Value)
        {
            NotifyCollectionChangedEventArgs E = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, Items[name]);
            Value = Items.Remove(name);
            if (Value)
            {
                RaiseCollectionChanged(E);
            }
        }
        return Value;
    }
    #endregion

    #region INotifyCollectionChanged Members
    public event NotifyCollectionChangedEventHandler CollectionChanged;
    private void RaiseCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        if (CollectionChanged != null)
        {
            CollectionChanged(this, e);
        }
    }
    #endregion
}
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-06-09 03:50:45

您的自定义集合看起来像是KeyedCollection<TKey,TItem>的翻版,它在内部使用字典并具有索引。如果TKeyintint-based枚举,但为this can be fixed,则int索引的索引器可能会被隐藏。

至于让KeyedCollection与WPF一起工作,我发现了this article,他基本上是通过实现INotifyCollectionChanged并覆盖SetItem()InsertItem()ClearItems()RemoveItem(),以及添加AddRange()并将< ObservableKeyedCollection<TKey,TItem> >d15传递给从TItem获取TKey的构造函数来创建代码。

票数 11
EN

Stack Overflow用户

发布于 2011-06-07 01:28:11

这有点间接,但是你可以用Linq做到这一点。不包括错误处理,您可以这样做:

代码语言:javascript
复制
var items = dict.Keys.Select((k, i) => new { idx = i, key = k });
var index = items.FirstOrDefault(f => f.key == name).idx;

同样,只要保持一致,您也可以使用值而不是键。

票数 2
EN

Stack Overflow用户

发布于 2011-06-09 03:39:05

因此,我通过将remove事件更改为reset来进行临时修改,并继续处理代码的其他部分。当我回到这个问题上时,我发现/意识到SortedList类将满足我的需求,并允许我在对现有代码进行最少更改的情况下正确地实现Collection Changed事件。

对于那些不熟悉这个类的人(我以前从未用过它),这里是基于我到目前为止所做的阅读的快速总结。虽然它的内部结构不同,但在大多数情况下,它的行为看起来像一本字典。此集合维护键和值的排序列表,而不是哈希表。这意味着将数据传入和传出集合需要更多的开销,但它的内存消耗更低。这种差异看起来有多明显,取决于您需要存储多少数据,以及您为键使用的数据类型。

由于我在这个实例中的数据量相对较小,并且我需要将列表框中的项按其name值进行排序,因此在我的情况下使用这个类似乎是一个很好的答案。如果任何人有理由不使用这个类,请让我知道。

感谢所有人的建议和评论,希望这个帖子能帮助其他人。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6255414

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档