WPF字典集合类ObservableDictionary

时间:2023-03-09 19:41:29
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版本来修改,那个更加有技术含量和可扩展性更强!