One of the core technical advantages of WPF is data binding. Data binding can update the interface by operating on data.
The two classes most commonly used for data binding are ObservableCollection
ObservableCollection represents a dynamic data collection. This collection will provide notifications when items are added, items are removed, or the entire list is refreshed. The interface display can be updated by updating the collection data.
Dictionary dictionary class has extremely poor retrieval and data operation performance, so some collections of configuration items are saved using it.
Therefore, everyone thought of whether there is a class that combines ObservableCollection and Dictionary, so the ObservableDictionary class was formed.
There are many versions of the ObservableDictionary class on the Internet. As far as I know, the earliest and most classic one is ItemsControl to a dictionary in Dr.WPF. Most other versions are modified with reference to this (the wrong one It’s just that I am ignorant).
The version I provide today also refers to other versions on the Internet and those in Dr.WPF.
The definition in Dr.WPF is like this:
public class ObservableDictionary <TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IDictionary, ICollection, IEnumerable, ISerializable, IDeserializationCallback, INotifyCollectionChanged, INotifyPropertyChanged
If you look carefully, you will find that the interface inherited here is the same as that inherited by Dictionary
So, the version I provide today directly inherits from Dictionary
I have tested it, there are no BUGs, and the performance is excellent. The code is as follows:
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 }
In terms of extension, you can modify it with the Dr.WPF version, which is more efficient More technical and more scalable!
The above is the detailed content of The core technology of WPF-data binding. For more information, please follow other related articles on the PHP Chinese website!