zoukankan      html  css  js  c++  java
  • WPF字典集合类ObservableDictionary

    WPF最核心的技术优势之一就是数据绑定。数据绑定,可以通过对数据的操作来更新界面。

    数据绑定最经常用到的是ObservableCollection<T> 和 Dictionary<T, T> 这两个类。

    ObservableCollection表示一个动态数据集合,在添加项、移除项或刷新整个列表时,此集合将提供通知,可以通过更新集合数据来更新界面显示。

    Dictionary字典类,检索和数据操作性能极性,所以一些配置项的集合都使用它来保存。

    因此,大家就想到的,有没有ObservableCollection和Dictionary相结合的类呢,于是就形成的ObservableDictionary类。

    网上有很多版本的ObservableDictionary类,据我了解到的,最早且最经典的就是Dr.WPF里面的ItemsControl to a dictionary,其他的版本多数是参考这个来修改的(不对的那就是我孤陋寡闻了)。

    今天我提供的这个版本,也是参考了网上的其他版本和Dr.WPF里的。

    Dr.WPF里的定义是这样的:

    public class ObservableDictionary <TKey, TValue> :
            IDictionary<TKey, TValue>,
            ICollection<KeyValuePair<TKey, TValue>>,
            IEnumerable<KeyValuePair<TKey, TValue>>,
            IDictionary,
            ICollection,
            IEnumerable,
            ISerializable,
            IDeserializationCallback,
            INotifyCollectionChanged,
            INotifyPropertyChanged
    

    大家细心点就会发现,这里继承的接口和Dictionary<TKey, TValue>所继承的大部分相同,只是多了INotifyCollectionChanged, INotifyPropertyChanged

    于是,今天我提供的版本,就直接继承于Dictionary<TKey, TValue>和INotifyCollectionChanged, INotifyPropertyChanged。

    本人测试过,无BUG,性能也极佳,下面上代码:

        public class ObservableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, INotifyCollectionChanged, INotifyPropertyChanged
        {
            public ObservableDictionary()
                : base()
            { }
    
            private int _index;
            public event NotifyCollectionChangedEventHandler CollectionChanged;
            public event PropertyChangedEventHandler PropertyChanged;
    
            public new KeyCollection Keys
            {
                get { return base.Keys; }
            }
    
            public new ValueCollection Values
            {
                get { return base.Values; }
            }
    
            public new int Count 
            {
                get { return base.Count; }
            }
    
            public new TValue this[TKey key]
            {
                get { return this.GetValue(key); }
                set { this.SetValue(key, value); }
            }
    
            public TValue this[int index]
            {
                get { return this.GetIndexValue(index); }
                set { this.SetIndexValue(index, value); }
            }
    
            public new void Add(TKey key, TValue value)
            {
                base.Add(key, value);
                this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, this.FindPair(key), _index));
                OnPropertyChanged("Keys");
                OnPropertyChanged("Values");
                OnPropertyChanged("Count");
            }
    
            public new void Clear()
            {
                base.Clear();
                this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
                OnPropertyChanged("Keys");
                OnPropertyChanged("Values");
                OnPropertyChanged("Count");
            }
    
            public new bool Remove(TKey key)
            {
                var pair = this.FindPair(key);
                if (base.Remove(key))
                {
                    this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, pair, _index));
                    OnPropertyChanged("Keys");
                    OnPropertyChanged("Values");
                    OnPropertyChanged("Count");
                    return true;
                }
                return false;
            }
    
            protected void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
            {
                if (this.CollectionChanged != null)
                {
                    this.CollectionChanged(this, e);
                }
            }
    
            protected void OnPropertyChanged(string propertyName)
            {
                if (this.PropertyChanged != null)
                {
                    this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
    
            #region private方法
            private TValue GetIndexValue(int index)
            {
                for (int i = 0; i < this.Count; i++)
                {
                    if (i == index)
                    {
                        var pair = this.ElementAt(i);
                        return pair.Value;
                    }
                }
    
                return default(TValue);
            }
    
            private void SetIndexValue(int index, TValue value)
            {
                try
                {
                    var pair = this.ElementAtOrDefault(index);
                    SetValue(pair.Key, value);                
                }
                catch (Exception)
                {
                    
                }
            }
    
            private TValue GetValue(TKey key)
            {
                if (base.ContainsKey(key))
                {
                    return base[key];
                }
                else
                {
                    return default(TValue);
                }
            }
    
            private void SetValue(TKey key, TValue value)
            {
                if (base.ContainsKey(key))
                {
                    var pair = this.FindPair(key);
                    int index = _index;
                    base[key] = value;
                    var newpair = this.FindPair(key);
                    this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, newpair, pair, index));
                    OnPropertyChanged("Values");
                    OnPropertyChanged("Item[]");
                }
                else
                {
                    this.Add(key, value);
                }
            }
    
            private KeyValuePair<TKey, TValue> FindPair(TKey key)
            {
                _index = 0;
                foreach (var item in this)
                {
                    if (item.Key.Equals(key))
                    {
                        return item;
                    }
                    _index++;
                }
                return default(KeyValuePair<TKey, TValue>);
            }
    
            private int IndexOf(TKey key)
            {
                int index = 0;
                foreach (var item in this)
                {
                    if (item.Key.Equals(key))
                    {
                        return index;
                    }
                    index++;
    
                }
                return -1;
            }
    
            #endregion
    
        }
    

    扩展方面,大家可以以Dr.WPF版本来修改,那个更加有技术含量和可扩展性更强!

  • 相关阅读:
    从零到一,使用实时音视频 SDK 一起开发一款 Zoom 吧
    七牛云助你度寒冬 | 每天 10:24, 新用户抢全额免单
    (下)挖掘传统行业日志大数据的无限价值
    (上)挖掘传统行业日志大数据的无限价值
    8.27 直播| 挖掘传统行业日志大数据的无限价值
    千亿级数量下日志分析系统的技术架构选型
    七牛云工程效率部测试服务如何为 70 万+ 客户保驾护航?
    云计算的新墨菲定律
    如何建设高吞吐量的日志平台
    新一代智能视频云发展现状分析:五大要素成关键
  • 原文地址:https://www.cnblogs.com/lisweden/p/7009600.html
Copyright © 2011-2022 走看看