【问题标题】:WPF - How can I implement an ObservableCollection<K,T> with a key (like a Dictionary)?WPF - 如何使用键(如字典)实现 ObservableCollection<K,T>?
【发布时间】:2010-09-29 02:31:13
【问题描述】:

我已经使用带有 WPF 的 ObservableCollection 进行绑定,并且效果很好。我现在真正想要的是一个像字典一样的字典,它有一个我可以使用的键,就像“ObservableCollection”一样有效。

您能否推荐可用于提供此类 ObservableCollection 的代码?目标是拥有一个可以从 WPF 绑定到的类似字典的结构。

谢谢

【问题讨论】:

    标签: c# .net wpf observablecollection


    【解决方案1】:

    Someone already made it。我还没有尝试过,但没有什么可失去的。

    【讨论】:

      【解决方案2】:

      怎么样:

      var collection = new ObservableCollection&lt;KeyValuePair&lt;TKey, TValue&gt;&gt;();

      你应该能够解决它:

      collection.First(x =&gt; x.Key == *your key value*).Key 或 .Value

      【讨论】:

        【解决方案3】:

        创建一个实现 IDictionary、INotifyCollectionChanged 和 INotifyPropertyChanged 接口的类。该类将有一个 Dictionary 实例,它将用于 IDictionary 的实现(其中一个 Add 方法在下面作为示例进行了编码)。 INotifyCollectionChanged 和 INotifyProperyChanged 都需要存在事件,这些事件应在包装函数中的适当位置触发(再次,请参阅下面的 Add 方法以获取示例)

        class ObservableDictionary<TKey, TValue> : IDictionary, INotifyCollectionChanged, INotifyPropertyChanged
        {
            private Dictionary<TKey, TValue> mDictionary;
            // Methods & Properties for IDictionary implementation would defer to mDictionary:
            public void Add(TKey key, TValue value){
                mDictionary.Add(key, value);
                OnCollectionChanged(NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, value)
                return;
            }
            // Implementation of INotifyCollectionChanged:
            public event NotifyCollectionChangedEventHandler CollectionChanged;
            protected void OnCollectionChanged(NotifyCollectionChangedEventArgs args){
                // event fire implementation
            }
            // Implementation of INotifyProperyChanged:
            public event ProperyChangedEventHandler ProperyChanged;
            protected void OnPropertyChanged(PropertyChangedEventArgs args){
                // event fire implementation
            }
        }
        

        编辑:

        请注意,直接或间接实现 IDictionary 接口需要实现三个额外的接口:

        ICollection<KeyValuePair<TKey,TValue>>
        IEnumerable<KeyValuePair<TKey,TValue>>
        IEnumerable.
        

        根据您的需要,您可能不必实现整个 IDictionary 接口,如果您只想调用几个方法,那么只需实现这些方法,IDictionary 接口就变得很奢侈了。但是,您必须实现 INotifyCollectionChanged 和 INotifyPropertyChanged 接口才能进行绑定。Blockquote

        【讨论】:

        • 把它放到 VS 我注意到还有更多的接口方法需要实现 - 这是正确的吗?
        • 是的,如果您的要求需要您实现整个 IDictionary 接口,请参阅我的编辑
        【解决方案4】:

        类似的东西呢:

        ObservableCollection<Tuple<string, object>>()
        

        其中字符串和对象以及示例类型当然

        【讨论】:

        • 根据使用情况,这可能有效。但是,请考虑在使用这样的元组时如何按键“查找”元素。字典可以使用散列通过键查找值,并且比在列表中搜索匹配键要快得多。
        • 你说得有道理。然而,对大型数据集使用可观察集合可能不是一个好主意。
        【解决方案5】:
        public class ObservableDictonary<TKey, TValue> : Dictionary<TKey, TValue>, INotifyCollectionChanged, INotifyPropertyChanged
        {
            public event NotifyCollectionChangedEventHandler CollectionChanged;
        
            public event PropertyChangedEventHandler PropertyChanged;
        
            public new void Add(TKey key, TValue value)
            {
                base.Add(key, value);
                if (!TryGetValue(key, out _)) return;
                var index = Keys.Count;
                OnPropertyChanged(nameof(Count));
                OnPropertyChanged(nameof(Values));
                OnCollectionChanged(NotifyCollectionChangedAction.Add, value, index);
            }
        
            public new void Remove(TKey key)
            {
                if (!TryGetValue(key, out var value)) return;
                var index = IndexOf(Keys, key);
                OnPropertyChanged(nameof(Count));
                OnPropertyChanged(nameof(Values));
                OnCollectionChanged(NotifyCollectionChangedAction.Remove, value, index);
                base.Remove(key);
            }
        
            public new void Clear()
            {
        
            }
        
            protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
            {
                PropertyChanged?.Invoke(this, e);
            }
        
            protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
            {
                CollectionChanged?.Invoke(this, e);
            }
        
            private void OnPropertyChanged(string propertyName)
            {
                OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
            }
        
            private void OnCollectionChanged(NotifyCollectionChangedAction action, object item)
            {
                OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item));
            }
        
            private void OnCollectionChanged(NotifyCollectionChangedAction action, object item, int index)
            {
                OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item, index));
            }
        
            private int IndexOf(KeyCollection keys, TKey key)
            {
                var index = 0;
                foreach (var k in keys)
                {
                    if (Equals(k, key))
                        return index;
                    index++;
                }
                return -1;
            }
        }
        

        我覆盖了添加、删除和清除。你必须明白,如果你使用扩展方法或简单方法,带有 Dictionary 参数,你不会看到变化,因为在这种情况下,Add 或 Remove 方法将使用 Dictionary(而不是 ObservableDictonary)。所以你必须直接 ObservableDictonary 的方法(添加或删除)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-08-20
          • 1970-01-01
          • 1970-01-01
          • 2011-09-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-09-29
          相关资源
          最近更新 更多