NotifyCollectionChangedEventArgs.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. #if !NETFX_CORE
  2. // Copyright (c) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
  4. using System;
  5. using System.Collections;
  6. using System.Diagnostics;
  7. namespace PlatformSupport.Collections.Specialized
  8. {
  9. public delegate void NotifyCollectionChangedEventHandler(object sender, PlatformSupport.Collections.Specialized.NotifyCollectionChangedEventArgs e);
  10. public interface INotifyCollectionChanged
  11. {
  12. event NotifyCollectionChangedEventHandler CollectionChanged;
  13. }
  14. /// <summary>
  15. /// This enum describes the action that caused a CollectionChanged event.
  16. /// </summary>
  17. public enum NotifyCollectionChangedAction
  18. {
  19. /// <summary> One or more items were added to the collection. </summary>
  20. Add,
  21. /// <summary> One or more items were removed from the collection. </summary>
  22. Remove,
  23. /// <summary> One or more items were replaced in the collection. </summary>
  24. Replace,
  25. /// <summary> One or more items were moved within the collection. </summary>
  26. Move,
  27. /// <summary> The contents of the collection changed dramatically. </summary>
  28. Reset,
  29. }
  30. /// <summary>
  31. /// Arguments for the CollectionChanged event.
  32. /// A collection that supports INotifyCollectionChangedThis raises this event
  33. /// whenever an item is added or removed, or when the contents of the collection
  34. /// changes dramatically.
  35. /// </summary>
  36. public class NotifyCollectionChangedEventArgs : EventArgs
  37. {
  38. //------------------------------------------------------
  39. //
  40. // Constructors
  41. //
  42. //------------------------------------------------------
  43. /// <summary>
  44. /// Construct a NotifyCollectionChangedEventArgs that describes a reset change.
  45. /// </summary>
  46. /// <param name="action">The action that caused the event (must be Reset).</param>
  47. public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action)
  48. {
  49. if (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset)
  50. throw new ArgumentException("action");
  51. InitializeAdd(action, null, -1);
  52. }
  53. /// <summary>
  54. /// Construct a NotifyCollectionChangedEventArgs that describes a one-item change.
  55. /// </summary>
  56. /// <param name="action">The action that caused the event; can only be Reset, Add or Remove action.</param>
  57. /// <param name="changedItem">The item affected by the change.</param>
  58. public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, object changedItem)
  59. {
  60. if ((action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Add) && (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Remove)
  61. && (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset))
  62. throw new ArgumentException("action");
  63. if (action == PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset)
  64. {
  65. if (changedItem != null)
  66. throw new ArgumentException("action");
  67. InitializeAdd(action, null, -1);
  68. }
  69. else
  70. {
  71. InitializeAddOrRemove(action, new object[] { changedItem }, -1);
  72. }
  73. }
  74. /// <summary>
  75. /// Construct a NotifyCollectionChangedEventArgs that describes a one-item change.
  76. /// </summary>
  77. /// <param name="action">The action that caused the event.</param>
  78. /// <param name="changedItem">The item affected by the change.</param>
  79. /// <param name="index">The index where the change occurred.</param>
  80. public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, object changedItem, int index)
  81. {
  82. if ((action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Add) && (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Remove)
  83. && (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset))
  84. throw new ArgumentException("action");
  85. if (action == PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset)
  86. {
  87. if (changedItem != null)
  88. throw new ArgumentException("action");
  89. if (index != -1)
  90. throw new ArgumentException("action");
  91. InitializeAdd(action, null, -1);
  92. }
  93. else
  94. {
  95. InitializeAddOrRemove(action, new object[] { changedItem }, index);
  96. }
  97. }
  98. /// <summary>
  99. /// Construct a NotifyCollectionChangedEventArgs that describes a multi-item change.
  100. /// </summary>
  101. /// <param name="action">The action that caused the event.</param>
  102. /// <param name="changedItems">The items affected by the change.</param>
  103. public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList changedItems)
  104. {
  105. if ((action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Add) && (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Remove)
  106. && (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset))
  107. throw new ArgumentException("action");
  108. if (action == PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset)
  109. {
  110. if (changedItems != null)
  111. throw new ArgumentException("action");
  112. InitializeAdd(action, null, -1);
  113. }
  114. else
  115. {
  116. if (changedItems == null)
  117. throw new ArgumentNullException("changedItems");
  118. InitializeAddOrRemove(action, changedItems, -1);
  119. }
  120. }
  121. /// <summary>
  122. /// Construct a NotifyCollectionChangedEventArgs that describes a multi-item change (or a reset).
  123. /// </summary>
  124. /// <param name="action">The action that caused the event.</param>
  125. /// <param name="changedItems">The items affected by the change.</param>
  126. /// <param name="startingIndex">The index where the change occurred.</param>
  127. public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList changedItems, int startingIndex)
  128. {
  129. if ((action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Add) && (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Remove)
  130. && (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset))
  131. throw new ArgumentException("action");
  132. if (action == PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset)
  133. {
  134. if (changedItems != null)
  135. throw new ArgumentException("action");
  136. if (startingIndex != -1)
  137. throw new ArgumentException("action");
  138. InitializeAdd(action, null, -1);
  139. }
  140. else
  141. {
  142. if (changedItems == null)
  143. throw new ArgumentNullException("changedItems");
  144. if (startingIndex < -1)
  145. throw new ArgumentException("startingIndex");
  146. InitializeAddOrRemove(action, changedItems, startingIndex);
  147. }
  148. }
  149. /// <summary>
  150. /// Construct a NotifyCollectionChangedEventArgs that describes a one-item Replace event.
  151. /// </summary>
  152. /// <param name="action">Can only be a Replace action.</param>
  153. /// <param name="newItem">The new item replacing the original item.</param>
  154. /// <param name="oldItem">The original item that is replaced.</param>
  155. public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, object newItem, object oldItem)
  156. {
  157. if (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Replace)
  158. throw new ArgumentException("action");
  159. InitializeMoveOrReplace(action, new object[] { newItem }, new object[] { oldItem }, -1, -1);
  160. }
  161. /// <summary>
  162. /// Construct a NotifyCollectionChangedEventArgs that describes a one-item Replace event.
  163. /// </summary>
  164. /// <param name="action">Can only be a Replace action.</param>
  165. /// <param name="newItem">The new item replacing the original item.</param>
  166. /// <param name="oldItem">The original item that is replaced.</param>
  167. /// <param name="index">The index of the item being replaced.</param>
  168. public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, object newItem, object oldItem, int index)
  169. {
  170. if (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Replace)
  171. throw new ArgumentException("action");
  172. InitializeMoveOrReplace(action, new object[] { newItem }, new object[] { oldItem }, index, index);
  173. }
  174. /// <summary>
  175. /// Construct a NotifyCollectionChangedEventArgs that describes a multi-item Replace event.
  176. /// </summary>
  177. /// <param name="action">Can only be a Replace action.</param>
  178. /// <param name="newItems">The new items replacing the original items.</param>
  179. /// <param name="oldItems">The original items that are replaced.</param>
  180. public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList newItems, IList oldItems)
  181. {
  182. if (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Replace)
  183. throw new ArgumentException("action");
  184. if (newItems == null)
  185. throw new ArgumentNullException("newItems");
  186. if (oldItems == null)
  187. throw new ArgumentNullException("oldItems");
  188. InitializeMoveOrReplace(action, newItems, oldItems, -1, -1);
  189. }
  190. /// <summary>
  191. /// Construct a NotifyCollectionChangedEventArgs that describes a multi-item Replace event.
  192. /// </summary>
  193. /// <param name="action">Can only be a Replace action.</param>
  194. /// <param name="newItems">The new items replacing the original items.</param>
  195. /// <param name="oldItems">The original items that are replaced.</param>
  196. /// <param name="startingIndex">The starting index of the items being replaced.</param>
  197. public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList newItems, IList oldItems, int startingIndex)
  198. {
  199. if (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Replace)
  200. throw new ArgumentException("action");
  201. if (newItems == null)
  202. throw new ArgumentNullException("newItems");
  203. if (oldItems == null)
  204. throw new ArgumentNullException("oldItems");
  205. InitializeMoveOrReplace(action, newItems, oldItems, startingIndex, startingIndex);
  206. }
  207. /// <summary>
  208. /// Construct a NotifyCollectionChangedEventArgs that describes a one-item Move event.
  209. /// </summary>
  210. /// <param name="action">Can only be a Move action.</param>
  211. /// <param name="changedItem">The item affected by the change.</param>
  212. /// <param name="index">The new index for the changed item.</param>
  213. /// <param name="oldIndex">The old index for the changed item.</param>
  214. public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, object changedItem, int index, int oldIndex)
  215. {
  216. if (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Move)
  217. throw new ArgumentException("action");
  218. if (index < 0)
  219. throw new ArgumentException("index");
  220. object[] changedItems = new object[] { changedItem };
  221. InitializeMoveOrReplace(action, changedItems, changedItems, index, oldIndex);
  222. }
  223. /// <summary>
  224. /// Construct a NotifyCollectionChangedEventArgs that describes a multi-item Move event.
  225. /// </summary>
  226. /// <param name="action">The action that caused the event.</param>
  227. /// <param name="changedItems">The items affected by the change.</param>
  228. /// <param name="index">The new index for the changed items.</param>
  229. /// <param name="oldIndex">The old index for the changed items.</param>
  230. public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList changedItems, int index, int oldIndex)
  231. {
  232. if (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Move)
  233. throw new ArgumentException("action");
  234. if (index < 0)
  235. throw new ArgumentException("index");
  236. InitializeMoveOrReplace(action, changedItems, changedItems, index, oldIndex);
  237. }
  238. /// <summary>
  239. /// Construct a NotifyCollectionChangedEventArgs with given fields (no validation). Used by WinRT marshaling.
  240. /// </summary>
  241. internal NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList newItems, IList oldItems, int newIndex, int oldIndex)
  242. {
  243. _action = action;
  244. _newItems = (newItems == null) ? null : new ReadOnlyList(newItems);
  245. _oldItems = (oldItems == null) ? null : new ReadOnlyList(oldItems);
  246. _newStartingIndex = newIndex;
  247. _oldStartingIndex = oldIndex;
  248. }
  249. private void InitializeAddOrRemove(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList changedItems, int startingIndex)
  250. {
  251. if (action == PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Add)
  252. InitializeAdd(action, changedItems, startingIndex);
  253. else if (action == PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Remove)
  254. InitializeRemove(action, changedItems, startingIndex);
  255. else
  256. Debug.Assert(false, String.Format("Unsupported action: {0}", action.ToString()));
  257. }
  258. private void InitializeAdd(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList newItems, int newStartingIndex)
  259. {
  260. _action = action;
  261. _newItems = (newItems == null) ? null : new ReadOnlyList(newItems);
  262. _newStartingIndex = newStartingIndex;
  263. }
  264. private void InitializeRemove(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList oldItems, int oldStartingIndex)
  265. {
  266. _action = action;
  267. _oldItems = (oldItems == null) ? null : new ReadOnlyList(oldItems);
  268. _oldStartingIndex = oldStartingIndex;
  269. }
  270. private void InitializeMoveOrReplace(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList newItems, IList oldItems, int startingIndex, int oldStartingIndex)
  271. {
  272. InitializeAdd(action, newItems, startingIndex);
  273. InitializeRemove(action, oldItems, oldStartingIndex);
  274. }
  275. //------------------------------------------------------
  276. //
  277. // Public Properties
  278. //
  279. //------------------------------------------------------
  280. /// <summary>
  281. /// The action that caused the event.
  282. /// </summary>
  283. public PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction Action
  284. {
  285. get { return _action; }
  286. }
  287. /// <summary>
  288. /// The items affected by the change.
  289. /// </summary>
  290. public IList NewItems
  291. {
  292. get { return _newItems; }
  293. }
  294. /// <summary>
  295. /// The old items affected by the change (for Replace events).
  296. /// </summary>
  297. public IList OldItems
  298. {
  299. get { return _oldItems; }
  300. }
  301. /// <summary>
  302. /// The index where the change occurred.
  303. /// </summary>
  304. public int NewStartingIndex
  305. {
  306. get { return _newStartingIndex; }
  307. }
  308. /// <summary>
  309. /// The old index where the change occurred (for Move events).
  310. /// </summary>
  311. public int OldStartingIndex
  312. {
  313. get { return _oldStartingIndex; }
  314. }
  315. //------------------------------------------------------
  316. //
  317. // Private Fields
  318. //
  319. //------------------------------------------------------
  320. private PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction _action;
  321. private IList _newItems, _oldItems;
  322. private int _newStartingIndex = -1;
  323. private int _oldStartingIndex = -1;
  324. }
  325. internal sealed class ReadOnlyList : IList
  326. {
  327. private readonly IList _list;
  328. internal ReadOnlyList(IList list)
  329. {
  330. Debug.Assert(list != null);
  331. _list = list;
  332. }
  333. public int Count
  334. {
  335. get { return _list.Count; }
  336. }
  337. public bool IsReadOnly
  338. {
  339. get { return true; }
  340. }
  341. public bool IsFixedSize
  342. {
  343. get { return true; }
  344. }
  345. public bool IsSynchronized
  346. {
  347. get { return _list.IsSynchronized; }
  348. }
  349. public object this[int index]
  350. {
  351. get
  352. {
  353. return _list[index];
  354. }
  355. set
  356. {
  357. throw new NotSupportedException();
  358. }
  359. }
  360. public object SyncRoot
  361. {
  362. get { return _list.SyncRoot; }
  363. }
  364. public int Add(object value)
  365. {
  366. throw new NotSupportedException();
  367. }
  368. public void Clear()
  369. {
  370. throw new NotSupportedException();
  371. }
  372. public bool Contains(object value)
  373. {
  374. return _list.Contains(value);
  375. }
  376. public void CopyTo(Array array, int index)
  377. {
  378. _list.CopyTo(array, index);
  379. }
  380. public IEnumerator GetEnumerator()
  381. {
  382. return _list.GetEnumerator();
  383. }
  384. public int IndexOf(object value)
  385. {
  386. return _list.IndexOf(value);
  387. }
  388. public void Insert(int index, object value)
  389. {
  390. throw new NotSupportedException();
  391. }
  392. public void Remove(object value)
  393. {
  394. throw new NotSupportedException();
  395. }
  396. public void RemoveAt(int index)
  397. {
  398. throw new NotSupportedException();
  399. }
  400. }
  401. }
  402. #endif