wasSharp – Blame information for rev 54
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
54 | office | 1 | /////////////////////////////////////////////////////////////////////////// |
2 | // Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 // |
||
3 | // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // |
||
4 | // rights of fair usage, the disclaimer and warranty conditions. // |
||
5 | /////////////////////////////////////////////////////////////////////////// |
||
6 | /// From https://gist.github.com/kzu/cfe3cb6e4fe3efea6d24 |
||
7 | |||
8 | using System; |
||
9 | using System.Collections; |
||
10 | using System.Collections.Generic; |
||
11 | using System.Collections.Specialized; |
||
12 | using System.ComponentModel; |
||
13 | using System.Diagnostics; |
||
14 | using System.Dynamic; |
||
15 | using System.Linq; |
||
16 | using System.Text; |
||
17 | using System.Threading.Tasks; |
||
18 | |||
19 | namespace wasSharp.Collections.Specialized |
||
20 | { |
||
21 | /// <summary> |
||
22 | /// Provides a dictionary for use with data binding. |
||
23 | /// </summary> |
||
24 | /// <typeparam name="TKey">Specifies the type of the keys in this collection.</typeparam> |
||
25 | /// <typeparam name="TValue">Specifies the type of the values in this collection.</typeparam> |
||
26 | [DebuggerDisplay("Count={Count}")] |
||
27 | public class ObservableDictionary<TKey, TValue> : |
||
28 | ICollection<KeyValuePair<TKey, TValue>>, IDictionary<TKey, TValue>, |
||
29 | INotifyCollectionChanged, INotifyPropertyChanged |
||
30 | { |
||
31 | readonly IDictionary<TKey, TValue> dictionary; |
||
32 | |||
33 | /// <summary>Event raised when the collection changes.</summary> |
||
34 | public event NotifyCollectionChangedEventHandler CollectionChanged = (sender, args) => { }; |
||
35 | |||
36 | /// <summary>Event raised when a property on the collection changes.</summary> |
||
37 | public event PropertyChangedEventHandler PropertyChanged = (sender, args) => { }; |
||
38 | |||
39 | /// <summary> |
||
40 | /// Initializes an instance of the class. |
||
41 | /// </summary> |
||
42 | public ObservableDictionary() |
||
43 | : this(new Dictionary<TKey, TValue>()) |
||
44 | { |
||
45 | } |
||
46 | |||
47 | /// <summary> |
||
48 | /// Initializes an instance of the class using another dictionary as |
||
49 | /// the key/value store. |
||
50 | /// </summary> |
||
51 | public ObservableDictionary(IDictionary<TKey, TValue> dictionary) |
||
52 | { |
||
53 | this.dictionary = dictionary; |
||
54 | } |
||
55 | |||
56 | void AddWithNotification(KeyValuePair<TKey, TValue> item) |
||
57 | { |
||
58 | AddWithNotification(item.Key, item.Value); |
||
59 | } |
||
60 | |||
61 | void AddWithNotification(TKey key, TValue value) |
||
62 | { |
||
63 | dictionary.Add(key, value); |
||
64 | |||
65 | CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, |
||
66 | new KeyValuePair<TKey, TValue>(key, value))); |
||
67 | PropertyChanged(this, new PropertyChangedEventArgs("Count")); |
||
68 | PropertyChanged(this, new PropertyChangedEventArgs("Keys")); |
||
69 | PropertyChanged(this, new PropertyChangedEventArgs("Values")); |
||
70 | } |
||
71 | |||
72 | bool RemoveWithNotification(TKey key) |
||
73 | { |
||
74 | TValue value; |
||
75 | if (dictionary.TryGetValue(key, out value) && dictionary.Remove(key)) |
||
76 | { |
||
77 | CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, |
||
78 | new KeyValuePair<TKey, TValue>(key, value))); |
||
79 | PropertyChanged(this, new PropertyChangedEventArgs("Count")); |
||
80 | PropertyChanged(this, new PropertyChangedEventArgs("Keys")); |
||
81 | PropertyChanged(this, new PropertyChangedEventArgs("Values")); |
||
82 | |||
83 | return true; |
||
84 | } |
||
85 | |||
86 | return false; |
||
87 | } |
||
88 | |||
89 | public void Clear() |
||
90 | { |
||
91 | dictionary.Clear(); |
||
92 | |||
93 | CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); |
||
94 | PropertyChanged(this, new PropertyChangedEventArgs("Count")); |
||
95 | PropertyChanged(this, new PropertyChangedEventArgs("Keys")); |
||
96 | PropertyChanged(this, new PropertyChangedEventArgs("Values")); |
||
97 | } |
||
98 | |||
99 | void UpdateWithNotification(TKey key, TValue value) |
||
100 | { |
||
101 | TValue existing; |
||
102 | if (dictionary.TryGetValue(key, out existing)) |
||
103 | { |
||
104 | dictionary[key] = value; |
||
105 | |||
106 | CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, |
||
107 | new KeyValuePair<TKey, TValue>(key, value), |
||
108 | new KeyValuePair<TKey, TValue>(key, existing))); |
||
109 | PropertyChanged(this, new PropertyChangedEventArgs("Values")); |
||
110 | } |
||
111 | else |
||
112 | { |
||
113 | AddWithNotification(key, value); |
||
114 | } |
||
115 | } |
||
116 | |||
117 | /// <summary> |
||
118 | /// Allows derived classes to raise custom property changed events. |
||
119 | /// </summary> |
||
120 | protected void RaisePropertyChanged(PropertyChangedEventArgs args) |
||
121 | { |
||
122 | PropertyChanged(this, args); |
||
123 | } |
||
124 | |||
125 | #region IDictionary<TKey,TValue> Members |
||
126 | |||
127 | /// <summary> |
||
128 | /// Adds an element with the provided key and value to the <see cref="T:System.Collections.Generic.IDictionary`2" />. |
||
129 | /// </summary> |
||
130 | /// <param name="key">The object to use as the key of the element to add.</param> |
||
131 | /// <param name="value">The object to use as the value of the element to add.</param> |
||
132 | public void Add(TKey key, TValue value) |
||
133 | { |
||
134 | AddWithNotification(key, value); |
||
135 | } |
||
136 | |||
137 | /// <summary> |
||
138 | /// Determines whether the <see cref="T:System.Collections.Generic.IDictionary`2" /> contains an element with the specified key. |
||
139 | /// </summary> |
||
140 | /// <param name="key">The key to locate in the <see cref="T:System.Collections.Generic.IDictionary`2" />.</param> |
||
141 | /// <returns> |
||
142 | /// true if the <see cref="T:System.Collections.Generic.IDictionary`2" /> contains an element with the key; otherwise, false. |
||
143 | /// </returns> |
||
144 | public bool ContainsKey(TKey key) |
||
145 | { |
||
146 | return dictionary.ContainsKey(key); |
||
147 | } |
||
148 | |||
149 | /// <summary> |
||
150 | /// Gets an <see cref="T:System.Collections.Generic.ICollection`1" /> containing the keys of the <see cref="T:System.Collections.Generic.IDictionary`2" />. |
||
151 | /// </summary> |
||
152 | /// <returns>An <see cref="T:System.Collections.Generic.ICollection`1" /> containing the keys of the object that implements <see cref="T:System.Collections.Generic.IDictionary`2" />.</returns> |
||
153 | public ICollection<TKey> Keys |
||
154 | { |
||
155 | get { return dictionary.Keys; } |
||
156 | } |
||
157 | |||
158 | /// <summary> |
||
159 | /// Removes the element with the specified key from the <see cref="T:System.Collections.Generic.IDictionary`2" />. |
||
160 | /// </summary> |
||
161 | /// <param name="key">The key of the element to remove.</param> |
||
162 | /// <returns> |
||
163 | /// true if the element is successfully removed; otherwise, false. This method also returns false if <paramref name="key" /> was not found in the original <see cref="T:System.Collections.Generic.IDictionary`2" />. |
||
164 | /// </returns> |
||
165 | public bool Remove(TKey key) |
||
166 | { |
||
167 | return RemoveWithNotification(key); |
||
168 | } |
||
169 | |||
170 | /// <summary> |
||
171 | /// Gets the value associated with the specified key. |
||
172 | /// </summary> |
||
173 | /// <param name="key">The key whose value to get.</param> |
||
174 | /// <param name="value">When this method returns, the value associated with the specified key, if the key is found; otherwise, the default value for the type of the <paramref name="value" /> parameter. This parameter is passed uninitialized.</param> |
||
175 | /// <returns> |
||
176 | /// true if the object that implements <see cref="T:System.Collections.Generic.IDictionary`2" /> contains an element with the specified key; otherwise, false. |
||
177 | /// </returns> |
||
178 | public bool TryGetValue(TKey key, out TValue value) |
||
179 | { |
||
180 | return dictionary.TryGetValue(key, out value); |
||
181 | } |
||
182 | |||
183 | /// <summary> |
||
184 | /// Gets an <see cref="T:System.Collections.Generic.ICollection`1" /> containing the values in the <see cref="T:System.Collections.Generic.IDictionary`2" />. |
||
185 | /// </summary> |
||
186 | /// <returns>An <see cref="T:System.Collections.Generic.ICollection`1" /> containing the values in the object that implements <see cref="T:System.Collections.Generic.IDictionary`2" />.</returns> |
||
187 | public ICollection<TValue> Values |
||
188 | { |
||
189 | get { return dictionary.Values; } |
||
190 | } |
||
191 | |||
192 | /// <summary> |
||
193 | /// Gets or sets the element with the specified key. |
||
194 | /// </summary> |
||
195 | /// <param name="key">The key.</param> |
||
196 | /// <returns></returns> |
||
197 | public TValue this[TKey key] |
||
198 | { |
||
199 | get { return dictionary[key]; } |
||
200 | set { UpdateWithNotification(key, value); } |
||
201 | } |
||
202 | |||
203 | #endregion |
||
204 | |||
205 | #region ICollection<KeyValuePair<TKey,TValue>> Members |
||
206 | |||
207 | void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item) |
||
208 | { |
||
209 | AddWithNotification(item); |
||
210 | } |
||
211 | |||
212 | void ICollection<KeyValuePair<TKey, TValue>>.Clear() |
||
213 | { |
||
214 | dictionary.Clear(); |
||
215 | |||
216 | CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); |
||
217 | PropertyChanged(this, new PropertyChangedEventArgs("Count")); |
||
218 | PropertyChanged(this, new PropertyChangedEventArgs("Keys")); |
||
219 | PropertyChanged(this, new PropertyChangedEventArgs("Values")); |
||
220 | } |
||
221 | |||
222 | bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item) => |
||
223 | dictionary.Contains(item); |
||
224 | |||
225 | void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) |
||
226 | { |
||
227 | dictionary.CopyTo(array, arrayIndex); |
||
228 | } |
||
229 | |||
230 | int ICollection<KeyValuePair<TKey, TValue>>.Count => |
||
231 | dictionary.Count(); |
||
232 | |||
233 | bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => |
||
234 | dictionary.IsReadOnly; |
||
235 | |||
236 | bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item) => |
||
237 | RemoveWithNotification(item.Key); |
||
238 | |||
239 | #endregion |
||
240 | |||
241 | #region IEnumerable<KeyValuePair<TKey,TValue>> Members |
||
242 | |||
243 | IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator() => |
||
244 | dictionary.GetEnumerator(); |
||
245 | |||
246 | IEnumerator IEnumerable.GetEnumerator() => |
||
247 | dictionary.GetEnumerator(); |
||
248 | |||
249 | #endregion |
||
250 | |||
251 | #region Extensions |
||
252 | public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() |
||
253 | { |
||
254 | return dictionary.GetEnumerator(); |
||
255 | } |
||
256 | #endregion |
||
257 | } |
||
258 | } |