1 //---------------------------------------------------------------------------
3 // <copyright file="NotifyCollectionChangedEventArgs.cs" company="Microsoft">
4 // Copyright (C) Microsoft Corporation. All rights reserved.
7 // Description: NotifyCollectionChanged event arguments
9 // Specs: http://avalon/connecteddata/Specs/INotifyCollectionChanged.mht
11 //---------------------------------------------------------------------------
14 using System.Collections;
15 using System.Diagnostics.Contracts;
16 using System.Runtime.CompilerServices;
18 namespace System.Collections.Specialized
21 /// This enum describes the action that caused a CollectionChanged event.
23 [TypeForwardedFrom("WindowsBase, Version=3.0.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]
24 public enum NotifyCollectionChangedAction
26 /// <summary> One or more items were added to the collection. </summary>
28 /// <summary> One or more items were removed from the collection. </summary>
30 /// <summary> One or more items were replaced in the collection. </summary>
32 /// <summary> One or more items were moved within the collection. </summary>
34 /// <summary> The contents of the collection changed dramatically. </summary>
39 /// Arguments for the CollectionChanged event.
40 /// A collection that supports INotifyCollectionChangedThis raises this event
41 /// whenever an item is added or removed, or when the contents of the collection
42 /// changes dramatically.
44 [TypeForwardedFrom("WindowsBase, Version=3.0.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]
45 public class NotifyCollectionChangedEventArgs : EventArgs
47 //------------------------------------------------------
51 //------------------------------------------------------
54 /// Construct a NotifyCollectionChangedEventArgs that describes a reset change.
56 /// <param name="action">The action that caused the event (must be Reset).</param>
57 public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action)
59 if (action != NotifyCollectionChangedAction.Reset)
60 throw new ArgumentException(SR.GetString(SR.WrongActionForCtor, NotifyCollectionChangedAction.Reset), "action");
62 InitializeAdd(action, null, -1);
66 /// Construct a NotifyCollectionChangedEventArgs that describes a one-item change.
68 /// <param name="action">The action that caused the event; can only be Reset, Add or Remove action.</param>
69 /// <param name="changedItem">The item affected by the change.</param>
70 public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object changedItem)
72 if ((action != NotifyCollectionChangedAction.Add) && (action != NotifyCollectionChangedAction.Remove)
73 && (action != NotifyCollectionChangedAction.Reset))
74 throw new ArgumentException(SR.GetString(SR.MustBeResetAddOrRemoveActionForCtor), "action");
76 if (action == NotifyCollectionChangedAction.Reset)
78 if (changedItem != null)
79 throw new ArgumentException(SR.GetString(SR.ResetActionRequiresNullItem), "action");
81 InitializeAdd(action, null, -1);
85 InitializeAddOrRemove(action, new object[]{changedItem}, -1);
90 /// Construct a NotifyCollectionChangedEventArgs that describes a one-item change.
92 /// <param name="action">The action that caused the event.</param>
93 /// <param name="changedItem">The item affected by the change.</param>
94 /// <param name="index">The index where the change occurred.</param>
95 public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object changedItem, int index)
97 if ((action != NotifyCollectionChangedAction.Add) && (action != NotifyCollectionChangedAction.Remove)
98 && (action != NotifyCollectionChangedAction.Reset))
99 throw new ArgumentException(SR.GetString(SR.MustBeResetAddOrRemoveActionForCtor), "action");
101 if (action == NotifyCollectionChangedAction.Reset)
103 if (changedItem != null)
104 throw new ArgumentException(SR.GetString(SR.ResetActionRequiresNullItem), "action");
106 throw new ArgumentException(SR.GetString(SR.ResetActionRequiresIndexMinus1), "action");
108 InitializeAdd(action, null, -1);
112 InitializeAddOrRemove(action, new object[]{changedItem}, index);
117 /// Construct a NotifyCollectionChangedEventArgs that describes a multi-item change.
119 /// <param name="action">The action that caused the event.</param>
120 /// <param name="changedItems">The items affected by the change.</param>
121 public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IList changedItems)
123 if ((action != NotifyCollectionChangedAction.Add) && (action != NotifyCollectionChangedAction.Remove)
124 && (action != NotifyCollectionChangedAction.Reset))
125 throw new ArgumentException(SR.GetString(SR.MustBeResetAddOrRemoveActionForCtor), "action");
127 if (action == NotifyCollectionChangedAction.Reset)
129 if (changedItems != null)
130 throw new ArgumentException(SR.GetString(SR.ResetActionRequiresNullItem), "action");
132 InitializeAdd(action, null, -1);
136 if (changedItems == null)
137 throw new ArgumentNullException("changedItems");
139 InitializeAddOrRemove(action, changedItems, -1);
144 /// Construct a NotifyCollectionChangedEventArgs that describes a multi-item change (or a reset).
146 /// <param name="action">The action that caused the event.</param>
147 /// <param name="changedItems">The items affected by the change.</param>
148 /// <param name="startingIndex">The index where the change occurred.</param>
149 public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IList changedItems, int startingIndex)
151 if ((action != NotifyCollectionChangedAction.Add) && (action != NotifyCollectionChangedAction.Remove)
152 && (action != NotifyCollectionChangedAction.Reset))
153 throw new ArgumentException(SR.GetString(SR.MustBeResetAddOrRemoveActionForCtor), "action");
155 if (action == NotifyCollectionChangedAction.Reset)
157 if (changedItems != null)
158 throw new ArgumentException(SR.GetString(SR.ResetActionRequiresNullItem), "action");
159 if (startingIndex != -1)
160 throw new ArgumentException(SR.GetString(SR.ResetActionRequiresIndexMinus1), "action");
162 InitializeAdd(action, null, -1);
166 if (changedItems == null)
167 throw new ArgumentNullException("changedItems");
168 if (startingIndex < -1)
169 throw new ArgumentException(SR.GetString(SR.IndexCannotBeNegative), "startingIndex");
171 InitializeAddOrRemove(action, changedItems, startingIndex);
176 /// Construct a NotifyCollectionChangedEventArgs that describes a one-item Replace event.
178 /// <param name="action">Can only be a Replace action.</param>
179 /// <param name="newItem">The new item replacing the original item.</param>
180 /// <param name="oldItem">The original item that is replaced.</param>
181 public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object newItem, object oldItem)
183 if (action != NotifyCollectionChangedAction.Replace)
184 throw new ArgumentException(SR.GetString(SR.WrongActionForCtor, NotifyCollectionChangedAction.Replace), "action");
186 InitializeMoveOrReplace(action, new object[]{newItem}, new object[]{oldItem}, -1, -1);
190 /// Construct a NotifyCollectionChangedEventArgs that describes a one-item Replace event.
192 /// <param name="action">Can only be a Replace action.</param>
193 /// <param name="newItem">The new item replacing the original item.</param>
194 /// <param name="oldItem">The original item that is replaced.</param>
195 /// <param name="index">The index of the item being replaced.</param>
196 public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object newItem, object oldItem, int index)
198 if (action != NotifyCollectionChangedAction.Replace)
199 throw new ArgumentException(SR.GetString(SR.WrongActionForCtor, NotifyCollectionChangedAction.Replace), "action");
201 int oldStartingIndex = index;
203 #if FEATURE_LEGACYNETCF
204 if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
206 // Dev11 444113 quirk:
207 // This is a "Replace" so the old and new index should both be set to the index passed in however
208 // NetCF on Mango incorrectly leaves OldStartingIndex at -1 and Mango apps depend on this behavior.
209 oldStartingIndex = -1;
212 InitializeMoveOrReplace(action, new object[]{newItem}, new object[]{oldItem}, index, oldStartingIndex);
216 /// Construct a NotifyCollectionChangedEventArgs that describes a multi-item Replace event.
218 /// <param name="action">Can only be a Replace action.</param>
219 /// <param name="newItems">The new items replacing the original items.</param>
220 /// <param name="oldItems">The original items that are replaced.</param>
221 public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IList newItems, IList oldItems)
223 if (action != NotifyCollectionChangedAction.Replace)
224 throw new ArgumentException(SR.GetString(SR.WrongActionForCtor, NotifyCollectionChangedAction.Replace), "action");
225 if (newItems == null)
226 throw new ArgumentNullException("newItems");
227 if (oldItems == null)
228 throw new ArgumentNullException("oldItems");
230 InitializeMoveOrReplace(action, newItems, oldItems, -1, -1);
234 /// Construct a NotifyCollectionChangedEventArgs that describes a multi-item Replace event.
236 /// <param name="action">Can only be a Replace action.</param>
237 /// <param name="newItems">The new items replacing the original items.</param>
238 /// <param name="oldItems">The original items that are replaced.</param>
239 /// <param name="startingIndex">The starting index of the items being replaced.</param>
240 public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IList newItems, IList oldItems, int startingIndex)
242 if (action != NotifyCollectionChangedAction.Replace)
243 throw new ArgumentException(SR.GetString(SR.WrongActionForCtor, NotifyCollectionChangedAction.Replace), "action");
244 if (newItems == null)
245 throw new ArgumentNullException("newItems");
246 if (oldItems == null)
247 throw new ArgumentNullException("oldItems");
249 InitializeMoveOrReplace(action, newItems, oldItems, startingIndex, startingIndex);
253 /// Construct a NotifyCollectionChangedEventArgs that describes a one-item Move event.
255 /// <param name="action">Can only be a Move action.</param>
256 /// <param name="changedItem">The item affected by the change.</param>
257 /// <param name="index">The new index for the changed item.</param>
258 /// <param name="oldIndex">The old index for the changed item.</param>
259 public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object changedItem, int index, int oldIndex)
261 if (action != NotifyCollectionChangedAction.Move)
262 throw new ArgumentException(SR.GetString(SR.WrongActionForCtor, NotifyCollectionChangedAction.Move), "action");
264 throw new ArgumentException(SR.GetString(SR.IndexCannotBeNegative), "index");
266 object[] changedItems= new object[] {changedItem};
267 InitializeMoveOrReplace(action, changedItems, changedItems, index, oldIndex);
271 /// Construct a NotifyCollectionChangedEventArgs that describes a multi-item Move event.
273 /// <param name="action">The action that caused the event.</param>
274 /// <param name="changedItems">The items affected by the change.</param>
275 /// <param name="index">The new index for the changed items.</param>
276 /// <param name="oldIndex">The old index for the changed items.</param>
277 public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IList changedItems, int index, int oldIndex)
279 if (action != NotifyCollectionChangedAction.Move)
280 throw new ArgumentException(SR.GetString(SR.WrongActionForCtor, NotifyCollectionChangedAction.Move), "action");
282 throw new ArgumentException(SR.GetString(SR.IndexCannotBeNegative), "index");
284 InitializeMoveOrReplace(action, changedItems, changedItems, index, oldIndex);
288 /// Construct a NotifyCollectionChangedEventArgs with given fields (no validation). Used by WinRT marshaling.
290 internal NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IList newItems, IList oldItems, int newIndex, int oldIndex)
293 #if FEATURE_LEGACYNETCF
294 if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
296 _newItems = newItems;
301 _newItems = (newItems == null) ? null : ArrayList.ReadOnly(newItems);
303 _oldItems = (oldItems == null) ? null : ArrayList.ReadOnly(oldItems);
304 _newStartingIndex = newIndex;
305 _oldStartingIndex = oldIndex;
308 private void InitializeAddOrRemove(NotifyCollectionChangedAction action, IList changedItems, int startingIndex)
310 if (action == NotifyCollectionChangedAction.Add)
311 InitializeAdd(action, changedItems, startingIndex);
312 else if (action == NotifyCollectionChangedAction.Remove)
313 InitializeRemove(action, changedItems, startingIndex);
315 Contract.Assert(false, String.Format("Unsupported action: {0}", action.ToString()));
318 private void InitializeAdd(NotifyCollectionChangedAction action, IList newItems, int newStartingIndex)
321 #if FEATURE_LEGACYNETCF
322 if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
324 _newItems = newItems;
327 #endif // !FEATURE_LEGACYNETCF
329 _newItems = (newItems == null) ? null : ArrayList.ReadOnly(newItems);
331 _newStartingIndex = newStartingIndex;
334 private void InitializeRemove(NotifyCollectionChangedAction action, IList oldItems, int oldStartingIndex)
337 _oldItems = (oldItems == null) ? null : ArrayList.ReadOnly(oldItems);
338 _oldStartingIndex= oldStartingIndex;
341 private void InitializeMoveOrReplace(NotifyCollectionChangedAction action, IList newItems, IList oldItems, int startingIndex, int oldStartingIndex)
343 InitializeAdd(action, newItems, startingIndex);
344 InitializeRemove(action, oldItems, oldStartingIndex);
347 //------------------------------------------------------
351 //------------------------------------------------------
354 /// The action that caused the event.
356 public NotifyCollectionChangedAction Action
358 get { return _action; }
362 /// The items affected by the change.
364 public IList NewItems
366 get { return _newItems; }
370 /// The old items affected by the change (for Replace events).
372 public IList OldItems
374 get { return _oldItems; }
378 /// The index where the change occurred.
380 public int NewStartingIndex
382 get { return _newStartingIndex; }
386 /// The old index where the change occurred (for Move events).
388 public int OldStartingIndex
390 get { return _oldStartingIndex; }
393 //------------------------------------------------------
397 //------------------------------------------------------
399 private NotifyCollectionChangedAction _action;
400 private IList _newItems, _oldItems;
401 private int _newStartingIndex = -1;
402 private int _oldStartingIndex = -1;
406 /// The delegate to use for handlers that receive the CollectionChanged event.
408 [TypeForwardedFrom("WindowsBase, Version=3.0.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]
409 public delegate void NotifyCollectionChangedEventHandler(object sender, NotifyCollectionChangedEventArgs e);