PageRenderTime 35ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/V1/trunk/Source/CAL/Composite.Wpf/Regions/ViewsCollection.cs

#
C# | 207 lines | 144 code | 17 blank | 46 comment | 15 complexity | 423149b2a188eabc9fd1ce9cd7140386 MD5 | raw file
  1. //===============================================================================
  2. // Microsoft patterns & practices
  3. // Composite Application Guidance for Windows Presentation Foundation
  4. //===============================================================================
  5. // Copyright (c) Microsoft Corporation. All rights reserved.
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
  7. // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
  8. // LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  9. // FITNESS FOR A PARTICULAR PURPOSE.
  10. //===============================================================================
  11. // The example companies, organizations, products, domain names,
  12. // e-mail addresses, logos, people, places, and events depicted
  13. // herein are fictitious. No association with any real company,
  14. // organization, product, domain name, email address, logo, person,
  15. // places, or events is intended or should be inferred.
  16. //===============================================================================
  17. using System;
  18. using System.Collections;
  19. using System.Collections.Generic;
  20. using System.Collections.ObjectModel;
  21. using System.Collections.Specialized;
  22. using System.Linq;
  23. using Microsoft.Practices.Composite.Regions;
  24. namespace Microsoft.Practices.Composite.Wpf.Regions
  25. {
  26. /// <summary>
  27. /// Implementation of <see cref="IViewsCollection"/> that takes an <see cref="ObservableCollection{T}"/> of <see cref="ItemMetadata"/>
  28. /// and filters it to display an <see cref="INotifyCollectionChanged"/> collection of
  29. /// <see cref="object"/> elements (the items which the <see cref="ItemMetadata"/> wraps).
  30. /// </summary>
  31. public class ViewsCollection : IViewsCollection
  32. {
  33. private readonly ObservableCollection<ItemMetadata> subjectCollection;
  34. private readonly Predicate<ItemMetadata> filter;
  35. private readonly List<object> filteredCollection = new List<object>();
  36. /// <summary>
  37. /// Initializes a new instance of <see cref="ViewsCollection"/>.
  38. /// </summary>
  39. /// <param name="list">The list to wrap and filter.</param>
  40. /// <param name="filter">A predicate to filter the <paramref name="list"/> collection.</param>
  41. public ViewsCollection(ObservableCollection<ItemMetadata> list, Predicate<ItemMetadata> filter)
  42. {
  43. this.subjectCollection = list;
  44. this.filter = filter;
  45. Initialize();
  46. subjectCollection.CollectionChanged += UnderlyingCollection_CollectionChanged;
  47. }
  48. /// <summary>
  49. /// Determines whether the collection contains a specific value.
  50. /// </summary>
  51. /// <param name="value">The object to locate in the collection.</param>
  52. /// <returns><see langword="true" /> if <paramref name="value"/> is found in the collection; otherwise, <see langword="false" />.</returns>
  53. public bool Contains(object value)
  54. {
  55. return filteredCollection.Contains(value);
  56. }
  57. ///<summary>
  58. ///Returns an enumerator that iterates through the collection.
  59. ///</summary>
  60. ///<returns>
  61. ///A <see cref="T:System.Collections.Generic.IEnumerator`1" /> that can be used to iterate through the collection.
  62. ///</returns>
  63. public IEnumerator<object> GetEnumerator()
  64. {
  65. return filteredCollection.GetEnumerator();
  66. }
  67. ///<summary>
  68. ///Returns an enumerator that iterates through a collection.
  69. ///</summary>
  70. ///<returns>
  71. ///An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.
  72. ///</returns>
  73. IEnumerator IEnumerable.GetEnumerator()
  74. {
  75. return GetEnumerator();
  76. }
  77. /// <summary>
  78. /// Occurs when the collection changes.
  79. /// </summary>
  80. public event NotifyCollectionChangedEventHandler CollectionChanged;
  81. private void AddAndNotify(object item)
  82. {
  83. AddAndNotify(new List<object>(1) { item });
  84. }
  85. private void AddAndNotify(IList items)
  86. {
  87. if (items.Count > 0)
  88. {
  89. filteredCollection.AddRange(items.Cast<object>());
  90. OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, items));
  91. }
  92. }
  93. private void RemoveAndNotify(object item)
  94. {
  95. RemoveAndNotify(new List<object>(1) { item });
  96. }
  97. private void RemoveAndNotify(IList items)
  98. {
  99. if (items.Count > 0)
  100. {
  101. int index = -1;
  102. if (items.Count == 1)
  103. {
  104. index = filteredCollection.IndexOf(items[0]);
  105. }
  106. foreach (object item in items)
  107. {
  108. filteredCollection.Remove(item);
  109. }
  110. OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, items, index));
  111. }
  112. }
  113. private void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
  114. {
  115. NotifyCollectionChangedEventHandler Handler = CollectionChanged;
  116. if (Handler != null) Handler(this, e);
  117. }
  118. private void Reset()
  119. {
  120. foreach (ItemMetadata itemMetadata in subjectCollection)
  121. {
  122. itemMetadata.MetadataChanged -= itemMetadata_MetadataChanged;
  123. }
  124. filteredCollection.Clear();
  125. Initialize();
  126. OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
  127. }
  128. private void Initialize()
  129. {
  130. foreach (ItemMetadata itemMetadata in subjectCollection)
  131. {
  132. itemMetadata.MetadataChanged += itemMetadata_MetadataChanged;
  133. if (filter(itemMetadata))
  134. {
  135. filteredCollection.Add(itemMetadata.Item);
  136. }
  137. }
  138. }
  139. void UnderlyingCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
  140. {
  141. List<object> changedItems = new List<object>();
  142. switch (e.Action)
  143. {
  144. case NotifyCollectionChangedAction.Add:
  145. foreach (ItemMetadata itemMetadata in e.NewItems)
  146. {
  147. itemMetadata.MetadataChanged += itemMetadata_MetadataChanged;
  148. if (filter(itemMetadata))
  149. {
  150. changedItems.Add(itemMetadata.Item);
  151. }
  152. }
  153. AddAndNotify(changedItems);
  154. break;
  155. case NotifyCollectionChangedAction.Remove:
  156. foreach (ItemMetadata itemMetadata in e.OldItems)
  157. {
  158. itemMetadata.MetadataChanged -= itemMetadata_MetadataChanged;
  159. if (filteredCollection.Contains(itemMetadata.Item))
  160. {
  161. changedItems.Add(itemMetadata.Item);
  162. }
  163. }
  164. RemoveAndNotify(changedItems);
  165. break;
  166. default:
  167. Reset();
  168. break;
  169. }
  170. }
  171. void itemMetadata_MetadataChanged(object sender, EventArgs e)
  172. {
  173. ItemMetadata itemMetadata = (ItemMetadata)sender;
  174. if (filteredCollection.Contains(itemMetadata.Item))
  175. {
  176. if (filter(itemMetadata) == false)
  177. {
  178. RemoveAndNotify(itemMetadata.Item);
  179. }
  180. }
  181. else
  182. {
  183. if (filter(itemMetadata) == true)
  184. {
  185. AddAndNotify(itemMetadata.Item);
  186. }
  187. }
  188. }
  189. }
  190. }