ObservableDictionary.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. using System.Collections.Specialized;
  2. using System.ComponentModel;
  3. using System.Linq;
  4. namespace UICommon.DataType;
  5. public class ObservableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, INotifyCollectionChanged, INotifyPropertyChanged where TKey : notnull
  6. {
  7. public ObservableDictionary() : base()
  8. { }
  9. private int _index;
  10. public event NotifyCollectionChangedEventHandler? CollectionChanged;
  11. public event PropertyChangedEventHandler? PropertyChanged;
  12. public new KeyCollection Keys => base.Keys;
  13. public new ValueCollection Values => base.Values;
  14. public new int Count => base.Count;
  15. public new TValue this[TKey key]
  16. {
  17. get
  18. {
  19. lock (this)
  20. return GetValue(key);
  21. }
  22. set
  23. {
  24. lock (this)
  25. SetValue(key, value);
  26. }
  27. }
  28. public TValue this[int index]
  29. {
  30. get
  31. {
  32. lock (this)
  33. return GetIndexValue(index);
  34. }
  35. set
  36. {
  37. lock (this)
  38. SetIndexValue(index, value);
  39. }
  40. }
  41. public new bool TryAdd(TKey key, TValue value)
  42. {
  43. lock (this)
  44. {
  45. if (this.ContainsKey(key))
  46. return false;
  47. this.Add(key, value);
  48. }
  49. return true;
  50. }
  51. public new bool TryGetValue(TKey key, out TValue? value)
  52. {
  53. lock (this)
  54. return base.TryGetValue(key, out value);
  55. }
  56. public new void Add(TKey key, TValue value)
  57. {
  58. lock (this)
  59. base.Add(key, value);
  60. OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, FindPair(key), _index));
  61. OnPropertyChanged(nameof(Keys));
  62. OnPropertyChanged(nameof(Values));
  63. OnPropertyChanged(nameof(Count));
  64. }
  65. public new void Clear()
  66. {
  67. lock (this)
  68. base.Clear();
  69. OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
  70. OnPropertyChanged(nameof(Keys));
  71. OnPropertyChanged(nameof(Values));
  72. OnPropertyChanged(nameof(Count));
  73. }
  74. public new bool Remove(TKey key)
  75. {
  76. var pair = FindPair(key);
  77. lock (this)
  78. if (base.Remove(key))
  79. {
  80. OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, pair, _index));
  81. OnPropertyChanged(nameof(Keys));
  82. OnPropertyChanged(nameof(Values));
  83. OnPropertyChanged(nameof(Count));
  84. return true;
  85. }
  86. return false;
  87. }
  88. protected void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
  89. {
  90. CollectionChanged?.Invoke(this, e);
  91. }
  92. protected void OnPropertyChanged(string propertyName)
  93. {
  94. PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  95. }
  96. #region private方法
  97. private TValue GetIndexValue(int index)
  98. {
  99. for (int i = 0; i < Count; i++)
  100. {
  101. if (i == index)
  102. {
  103. var pair = this.ElementAt(i);
  104. return pair.Value;
  105. }
  106. }
  107. return default!;
  108. }
  109. private void SetIndexValue(int index, TValue value)
  110. {
  111. try
  112. {
  113. var pair = this.ElementAtOrDefault(index);
  114. SetValue(pair.Key, value);
  115. }
  116. catch (Exception)
  117. {
  118. }
  119. }
  120. private TValue GetValue(TKey key)
  121. {
  122. return ContainsKey(key) ? base[key] : default!;
  123. }
  124. private void SetValue(TKey key, TValue value)
  125. {
  126. if (ContainsKey(key))
  127. {
  128. var pair = FindPair(key);
  129. int index = _index;
  130. base[key] = value;
  131. var newpair = FindPair(key);
  132. OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, newpair, pair, index));
  133. OnPropertyChanged(nameof(Values));
  134. OnPropertyChanged("Item[]");
  135. }
  136. else
  137. {
  138. Add(key, value);
  139. }
  140. }
  141. private KeyValuePair<TKey, TValue> FindPair(TKey key)
  142. {
  143. _index = 0;
  144. foreach (var item in this)
  145. {
  146. if (item.Key!.Equals(key))
  147. return item;
  148. _index++;
  149. }
  150. return default;
  151. }
  152. private int IndexOf(TKey key)
  153. {
  154. int index = 0;
  155. foreach (var item in this)
  156. {
  157. if (item.Key!.Equals(key))
  158. return index;
  159. index++;
  160. }
  161. return -1;
  162. }
  163. #endregion
  164. }