code_junkie

When Clearing an ObservableCollection, There are No Items in e.OldItems

Nov 11th, 2011
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.60 KB | None | 0 0
  1. <Window
  2. x:Class="ObservableCollection.Window1"
  3. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  4. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  5. Title="Window1"
  6. Height="300"
  7. Width="300"
  8. >
  9. <StackPanel>
  10. <Button x:Name="addButton" Content="Add" Width="100" Height="25" Margin="10" Click="addButton_Click"/>
  11. <Button x:Name="moveButton" Content="Move" Width="100" Height="25" Margin="10" Click="moveButton_Click"/>
  12. <Button x:Name="removeButton" Content="Remove" Width="100" Height="25" Margin="10" Click="removeButton_Click"/>
  13. <Button x:Name="replaceButton" Content="Replace" Width="100" Height="25" Margin="10" Click="replaceButton_Click"/>
  14. <Button x:Name="resetButton" Content="Reset" Width="100" Height="25" Margin="10" Click="resetButton_Click"/>
  15. </StackPanel>
  16. </Window>
  17.  
  18. using System;
  19. using System.Collections.Generic;
  20. using System.Linq;
  21. using System.Text;
  22. using System.Windows;
  23. using System.Windows.Controls;
  24. using System.Windows.Data;
  25. using System.Windows.Documents;
  26. using System.Windows.Input;
  27. using System.Windows.Media;
  28. using System.Windows.Media.Imaging;
  29. using System.Windows.Navigation;
  30. using System.Windows.Shapes;
  31. using System.Collections.ObjectModel;
  32.  
  33. namespace ObservableCollection
  34. {
  35. /// <summary>
  36. /// Interaction logic for Window1.xaml
  37. /// </summary>
  38. public partial class Window1 : Window
  39. {
  40. public Window1()
  41. {
  42. InitializeComponent();
  43. _integerObservableCollection.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(_integerObservableCollection_CollectionChanged);
  44. }
  45.  
  46. private void _integerObservableCollection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
  47. {
  48. switch (e.Action)
  49. {
  50. case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
  51. break;
  52. case System.Collections.Specialized.NotifyCollectionChangedAction.Move:
  53. break;
  54. case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
  55. break;
  56. case System.Collections.Specialized.NotifyCollectionChangedAction.Replace:
  57. break;
  58. case System.Collections.Specialized.NotifyCollectionChangedAction.Reset:
  59. break;
  60. default:
  61. break;
  62. }
  63. }
  64.  
  65. private void addButton_Click(object sender, RoutedEventArgs e)
  66. {
  67. _integerObservableCollection.Add(25);
  68. }
  69.  
  70. private void moveButton_Click(object sender, RoutedEventArgs e)
  71. {
  72. _integerObservableCollection.Move(0, 19);
  73. }
  74.  
  75. private void removeButton_Click(object sender, RoutedEventArgs e)
  76. {
  77. _integerObservableCollection.RemoveAt(0);
  78. }
  79.  
  80. private void replaceButton_Click(object sender, RoutedEventArgs e)
  81. {
  82. _integerObservableCollection[0] = 50;
  83. }
  84.  
  85. private void resetButton_Click(object sender, RoutedEventArgs e)
  86. {
  87. _integerObservableCollection.Clear();
  88. }
  89.  
  90. private ObservableCollection<int> _integerObservableCollection = new ObservableCollection<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 };
  91. }
  92. }
  93.  
  94. public static void RemoveAll(this IList list)
  95. {
  96. while (list.Count > 0)
  97. {
  98. list.RemoveAt(list.Count - 1);
  99. }
  100. }
  101.  
  102. public class TrulyObservableCollection<T> : ObservableCollection<T>
  103. {
  104. public event EventHandler<EventArgs> Clearing;
  105. protected virtual void OnClearing(EventArgs e)
  106. {
  107. if (Clearing != null)
  108. Clearing(this, e);
  109. }
  110.  
  111. protected override void ClearItems()
  112. {
  113. OnClearing(EventArgs.Empty);
  114. base.ClearItems();
  115. }
  116. }
  117.  
  118. /// <summary>
  119. /// An observable collection with support for addrange and clear
  120. /// </summary>
  121. /// <typeparam name="T"></typeparam>
  122. [Serializable]
  123. [TypeConverter(typeof(ExpandableObjectConverter))]
  124. public class ObservableCollectionRange<T> : ObservableCollection<T>
  125. {
  126. private bool _addingRange;
  127.  
  128. [field: NonSerialized]
  129. public event NotifyCollectionChangedEventHandler CollectionChangedRange;
  130.  
  131. protected virtual void OnCollectionChangedRange(NotifyCollectionChangedEventArgs e)
  132. {
  133. if ((CollectionChangedRange == null) || _addingRange) return;
  134. using (BlockReentrancy())
  135. {
  136. CollectionChangedRange(this, e);
  137. }
  138. }
  139.  
  140. public void AddRange(IEnumerable<T> collection)
  141. {
  142. CheckReentrancy();
  143. var newItems = new List<T>();
  144. if ((collection == null) || (Items == null)) return;
  145. using (var enumerator = collection.GetEnumerator())
  146. {
  147. while (enumerator.MoveNext())
  148. {
  149. _addingRange = true;
  150. Add(enumerator.Current);
  151. _addingRange = false;
  152. newItems.Add(enumerator.Current);
  153. }
  154. }
  155. OnCollectionChangedRange(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, newItems));
  156. }
  157.  
  158. protected override void ClearItems()
  159. {
  160. CheckReentrancy();
  161. var oldItems = new List<T>(this);
  162. base.ClearItems();
  163. OnCollectionChangedRange(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, oldItems));
  164. }
  165.  
  166. protected override void InsertItem(int index, T item)
  167. {
  168. CheckReentrancy();
  169. base.InsertItem(index, item);
  170. OnCollectionChangedRange(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index));
  171. }
  172.  
  173. protected override void MoveItem(int oldIndex, int newIndex)
  174. {
  175. CheckReentrancy();
  176. var item = base[oldIndex];
  177. base.MoveItem(oldIndex, newIndex);
  178. OnCollectionChangedRange(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Move, item, newIndex, oldIndex));
  179. }
  180.  
  181. protected override void RemoveItem(int index)
  182. {
  183. CheckReentrancy();
  184. var item = base[index];
  185. base.RemoveItem(index);
  186. OnCollectionChangedRange(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index));
  187. }
  188.  
  189. protected override void SetItem(int index, T item)
  190. {
  191. CheckReentrancy();
  192. var oldItem = base[index];
  193. base.SetItem(index, item);
  194. OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, oldItem, item, index));
  195. }
  196. }
  197.  
  198. /// <summary>
  199. /// A read only observable collection with support for addrange and clear
  200. /// </summary>
  201. /// <typeparam name="T"></typeparam>
  202. [Serializable]
  203. [TypeConverter(typeof(ExpandableObjectConverter))]
  204. public class ReadOnlyObservableCollectionRange<T> : ReadOnlyObservableCollection<T>
  205. {
  206. [field: NonSerialized]
  207. public event NotifyCollectionChangedEventHandler CollectionChangedRange;
  208.  
  209. public ReadOnlyObservableCollectionRange(ObservableCollectionRange<T> list) : base(list)
  210. {
  211. list.CollectionChangedRange += HandleCollectionChangedRange;
  212. }
  213.  
  214. private void HandleCollectionChangedRange(object sender, NotifyCollectionChangedEventArgs e)
  215. {
  216. OnCollectionChangedRange(e);
  217. }
  218.  
  219. protected virtual void OnCollectionChangedRange(NotifyCollectionChangedEventArgs args)
  220. {
  221. if (CollectionChangedRange != null)
  222. {
  223. CollectionChangedRange(this, args);
  224. }
  225. }
  226.  
  227. }
  228.  
  229. protected override void ClearItems()
  230. {
  231. CheckReentrancy();
  232. List<TItem> oldItems = new List<TItem>(Items);
  233.  
  234. Items.Clear();
  235.  
  236. OnPropertyChanged(new PropertyChangedEventArgs("Count"));
  237. OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
  238.  
  239. NotifyCollectionChangedEventArgs e =
  240. new NotifyCollectionChangedEventArgs
  241. (
  242. NotifyCollectionChangedAction.Reset
  243. );
  244.  
  245. FieldInfo field =
  246. e.GetType().GetField
  247. (
  248. "_oldItems",
  249. BindingFlags.Instance | BindingFlags.NonPublic
  250. );
  251. field.SetValue(e, oldItems);
  252.  
  253. OnCollectionChanged(e);
  254. }
  255.  
  256. using System;
  257. using System.Collections.Generic;
  258.  
  259. /// <summary>
  260. /// Notifies listeners of the following situations:
  261. /// <list type="bullet">
  262. /// <item>Elements have been added.</item>
  263. /// <item>Elements are about to be removed.</item>
  264. /// </list>
  265. /// </summary>
  266. /// <typeparam name="T">The type of elements in the collection.</typeparam>
  267. interface INotifyCollection<T>
  268. {
  269. /// <summary>
  270. /// Occurs when elements have been added.
  271. /// </summary>
  272. event EventHandler<NotifyCollectionEventArgs<T>> Added;
  273.  
  274. /// <summary>
  275. /// Occurs when elements are about to be removed.
  276. /// </summary>
  277. event EventHandler<NotifyCollectionEventArgs<T>> Removing;
  278. }
  279.  
  280. /// <summary>
  281. /// Provides data for the NotifyCollection event.
  282. /// </summary>
  283. /// <typeparam name="T">The type of elements in the collection.</typeparam>
  284. public class NotifyCollectionEventArgs<T> : EventArgs
  285. {
  286. /// <summary>
  287. /// Gets or sets the elements.
  288. /// </summary>
  289. /// <value>The elements.</value>
  290. public IEnumerable<T> Items
  291. {
  292. get;
  293. set;
  294. }
  295. }
  296.  
  297. /// <summary>
  298. /// An observable collection that cannot be reset. When clear is called
  299. /// items are removed individually, giving listeners the chance to detect
  300. /// each remove event and perform operations such as unhooking event
  301. /// handlers.
  302. /// </summary>
  303. /// <typeparam name="T">The type of item in the collection.</typeparam>
  304. public class NoResetObservableCollection<T> : ObservableCollection<T>
  305. {
  306. public NoResetObservableCollection()
  307. {
  308. }
  309.  
  310. /// <summary>
  311. /// Clears all items in the collection by removing them individually.
  312. /// </summary>
  313. protected override void ClearItems()
  314. {
  315. IList<T> items = new List<T>(this);
  316. foreach (T item in items)
  317. {
  318. Remove(item);
  319. }
  320. }
  321. }
  322.  
  323. /// <summary>
  324. /// Helper class that allows to "detach" all current Eventhandlers by setting
  325. /// DelegateHandler to null.
  326. /// </summary>
  327. public class PropertyChangedDelegator
  328. {
  329. /// <summary>
  330. /// Callback to the real event handling code.
  331. /// </summary>
  332. public PropertyChangedEventHandler DelegateHandler;
  333. /// <summary>
  334. /// Eventhandler that is registered by the elements.
  335. /// </summary>
  336. /// <param name="sender">the element that has been changed.</param>
  337. /// <param name="e">the event arguments</param>
  338. public void PropertyChangedHandler(Object sender, PropertyChangedEventArgs e)
  339. {
  340. if (DelegateHandler != null)
  341. {
  342. DelegateHandler(sender, e);
  343. }
  344. else
  345. {
  346. INotifyPropertyChanged s = sender as INotifyPropertyChanged;
  347. if (s != null)
  348. s.PropertyChanged -= PropertyChangedHandler;
  349. }
  350. }
  351. }
  352.  
  353. using System;
  354. using System.Collections.Generic;
  355. using System.Collections.ObjectModel;
  356. using System.Collections.Specialized;
  357. using System.Reflection;
  358.  
  359. namespace WpfUtil.Collections
  360. {
  361. public static class ObservableCollectionExtension
  362. {
  363. public static void RemoveAllOneByOne<T>(this ObservableCollection<T> obsColl)
  364. {
  365. foreach (T item in obsColl)
  366. {
  367. while (obsColl.Count > 0)
  368. {
  369. obsColl.RemoveAt(0);
  370. }
  371. }
  372. }
  373.  
  374. public static void RemoveAll<T>(this ObservableCollection<T> obsColl)
  375. {
  376. if (obsColl.Count > 0)
  377. {
  378. List<T> removedItems = new List<T>(obsColl);
  379. obsColl.Clear();
  380.  
  381. NotifyCollectionChangedEventArgs e =
  382. new NotifyCollectionChangedEventArgs
  383. (
  384. NotifyCollectionChangedAction.Remove,
  385. removedItems
  386. );
  387. var eventInfo =
  388. obsColl.GetType().GetField
  389. (
  390. "CollectionChanged",
  391. BindingFlags.Instance | BindingFlags.NonPublic
  392. );
  393. if (eventInfo != null)
  394. {
  395. var eventMember = eventInfo.GetValue(obsColl);
  396. // note: if eventMember is null
  397. // nobody registered to the event, you can't call it.
  398. if (eventMember != null)
  399. eventMember.GetType().GetMethod("Invoke").
  400. Invoke(eventMember, new object[] { obsColl, e });
  401. }
  402. }
  403. }
  404. }
  405. }
Add Comment
Please, Sign In to add comment