PageRenderTime 41ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/Blocks/Configuration/Src/Design/ViewModel/ValidationModel.cs

#
C# | 253 lines | 183 code | 36 blank | 34 comment | 21 complexity | 3a50b6fe8b560c68af916e7bd0bc9f88 MD5 | raw file
  1. //===============================================================================
  2. // Microsoft patterns & practices Enterprise Library
  3. // Core
  4. //===============================================================================
  5. // Copyright Š 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. using System;
  12. using System.Collections.Generic;
  13. using System.Collections.Specialized;
  14. using System.Configuration;
  15. using System.Windows.Input;
  16. using Microsoft.Practices.EnterpriseLibrary.Configuration.Design.Validation;
  17. using Microsoft.Practices.EnterpriseLibrary.Configuration.Design.ViewModel.Services;
  18. using Microsoft.Practices.Unity.Utility;
  19. namespace Microsoft.Practices.EnterpriseLibrary.Configuration.Design.ViewModel
  20. {
  21. /// <summary>
  22. /// The <see cref="ValidationModel"/> tracks all <see cref="ValidationResult"/> instances
  23. /// by elements in <see cref="ElementLookup"/>.
  24. /// </summary>
  25. /// <remarks>
  26. /// The <see cref="ValidationModel"/> monitors changes in <see cref="ElementLookup"/> and as new <see cref="ElementViewModel"/> are
  27. /// added begins montoring their <see cref="ElementViewModel.ValidationResults"/> and their properties' validation results.
  28. /// <br/>
  29. /// As results are added or removed for each element, this model keeps this list up-to-date for display in the design-time user interface.
  30. /// </remarks>
  31. public class ValidationModel
  32. {
  33. private readonly ElementLookup lookup;
  34. private readonly CompositeValidationResultsCollection resultsCollection = new CompositeValidationResultsCollection();
  35. private readonly NavigateValidationResultCommand navigateValidationResultCommand;
  36. private readonly List<ElementViewModel> elementsMonitored = new List<ElementViewModel>();
  37. private bool populating = false;
  38. ///<summary>
  39. /// Initializes a new instance of <see cref="ValidationModel"/>.
  40. ///</summary>
  41. ///<param name="lookup">The element loookup service to use for monitoring the addition and removal of <see cref="ElementViewModel"/> items.</param>
  42. public ValidationModel(ElementLookup lookup)
  43. {
  44. this.lookup = lookup;
  45. this.navigateValidationResultCommand = new NavigateValidationResultCommand(this);
  46. ResetCollection();
  47. lookup.CollectionChanged += ElementsChanged;
  48. }
  49. private void ElementsChanged(object sender, NotifyCollectionChangedEventArgs e)
  50. {
  51. if (e.Action == NotifyCollectionChangedAction.Add)
  52. {
  53. foreach (var item in e.NewItems)
  54. {
  55. var elementViewModel = item as ElementViewModel;
  56. if (elementViewModel == null) continue;
  57. AddElementResultsCollections(elementViewModel);
  58. }
  59. }
  60. if (e.Action == NotifyCollectionChangedAction.Remove)
  61. {
  62. foreach (var item in e.OldItems)
  63. {
  64. var elementViewModel = item as ElementViewModel;
  65. if (elementViewModel == null) continue;
  66. RemoveElementResultsCollections(elementViewModel);
  67. }
  68. }
  69. if (e.Action == NotifyCollectionChangedAction.Reset)
  70. {
  71. ResetCollection();
  72. }
  73. }
  74. private void ResetCollection()
  75. {
  76. resultsCollection.NotifyEnabled = false;
  77. ClearElementsMonitored();
  78. resultsCollection.Clear();
  79. PopulateCollection();
  80. resultsCollection.NotifyEnabled = true;
  81. }
  82. private void PopulateCollection()
  83. {
  84. populating = true;
  85. foreach (var section in lookup.FindInstancesOfConfigurationType(typeof(ConfigurationSection)))
  86. {
  87. AddElementResultsCollections(section);
  88. }
  89. populating = false;
  90. }
  91. private void RemoveElementResultsCollections(ElementViewModel element)
  92. {
  93. resultsCollection.Remove(element.ValidationResults);
  94. foreach (var prop in element.Properties)
  95. {
  96. resultsCollection.Remove(prop.ValidationResults);
  97. }
  98. foreach (var child in element.ChildElements)
  99. {
  100. RemoveElementResultsCollections(child);
  101. }
  102. RemoveElementPropertyMonitoring(element);
  103. }
  104. private void AddElementResultsCollections(ElementViewModel element)
  105. {
  106. resultsCollection.Add(element.ValidationResults);
  107. foreach (var prop in element.Properties)
  108. {
  109. resultsCollection.Add(prop.ValidationResults);
  110. }
  111. foreach (var child in element.ChildElements)
  112. {
  113. AddElementResultsCollections(child);
  114. }
  115. AddElementPropertyMonitoring(element);
  116. }
  117. /// <summary>
  118. /// Orientates the designer to the configuration element associated with the given <see cref="ValidationResult"/>.
  119. /// </summary>
  120. /// <param name="validationResult">The <see cref="ValidationResult"/> that should be navigated to.</param>
  121. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", Justification = "Validated with Guard class")]
  122. public void Navigate(ValidationResult validationResult)
  123. {
  124. Guard.ArgumentNotNull(validationResult, "validationResult");
  125. var elementWithError = lookup.GetElementById(validationResult.ElementId);
  126. if (elementWithError != null)
  127. {
  128. if (!(elementWithError is SectionViewModel))
  129. {
  130. elementWithError.ContainingSection.ExpandSection();
  131. }
  132. elementWithError.PropertiesShown = true;
  133. elementWithError.Select();
  134. }
  135. }
  136. /// <summary>
  137. /// Provides an <see cref="ICommand"/> implementation that allows to execute the <see cref="ValidationModel.Navigate"/> method from within XAML.
  138. /// </summary>
  139. public ICommand NavigateCommand
  140. {
  141. get { return this.navigateValidationResultCommand; }
  142. }
  143. ///<summary>
  144. /// Gets the set of validation results collected from all elements.
  145. ///</summary>
  146. public IEnumerable<ValidationResult> ValidationResults
  147. {
  148. get { return resultsCollection; }
  149. }
  150. private void RemoveElementPropertyMonitoring(ElementViewModel element)
  151. {
  152. this.elementsMonitored.Remove(element);
  153. element.Properties.CollectionChanged -= ElementPropertiesCollectionChangedHandler;
  154. }
  155. private void AddElementPropertyMonitoring(ElementViewModel element)
  156. {
  157. if (!elementsMonitored.Contains(element))
  158. {
  159. this.elementsMonitored.Add(element);
  160. element.Properties.CollectionChanged += ElementPropertiesCollectionChangedHandler;
  161. }
  162. }
  163. private void ClearElementsMonitored()
  164. {
  165. foreach (var element in elementsMonitored)
  166. {
  167. element.Properties.CollectionChanged -= ElementPropertiesCollectionChangedHandler;
  168. }
  169. elementsMonitored.Clear();
  170. }
  171. private void ElementPropertiesCollectionChangedHandler(object sender, NotifyCollectionChangedEventArgs e)
  172. {
  173. if (populating) return;
  174. if (e.Action == NotifyCollectionChangedAction.Reset)
  175. {
  176. ResetCollection();
  177. }
  178. else
  179. {
  180. if (e.OldItems != null)
  181. {
  182. foreach (var oldItem in e.OldItems)
  183. {
  184. resultsCollection.Remove(((Property)oldItem).ValidationResults);
  185. }
  186. }
  187. if (e.NewItems != null)
  188. {
  189. foreach (var newItem in e.NewItems)
  190. {
  191. resultsCollection.Add(((Property)newItem).ValidationResults);
  192. }
  193. }
  194. }
  195. }
  196. private class NavigateValidationResultCommand : ICommand
  197. {
  198. private readonly ValidationModel validationModel;
  199. public NavigateValidationResultCommand(ValidationModel validationModel)
  200. {
  201. this.validationModel = validationModel;
  202. }
  203. public bool CanExecute(object parameter)
  204. {
  205. return parameter is ValidationResult;
  206. }
  207. #pragma warning disable 67
  208. public event EventHandler CanExecuteChanged;
  209. #pragma warning restore 67
  210. public void Execute(object parameter)
  211. {
  212. ValidationResult result = (ValidationResult)parameter;
  213. validationModel.Navigate(result);
  214. }
  215. }
  216. }
  217. }