PageRenderTime 51ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

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

#
C# | 247 lines | 129 code | 26 blank | 92 comment | 18 complexity | f8997fcaaf35870d2134b9c8e14b4058 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.Generic;
  19. using System.Globalization;
  20. using System.Windows;
  21. using Microsoft.Practices.Composite.Regions;
  22. using Microsoft.Practices.Composite.Wpf.Properties;
  23. namespace Microsoft.Practices.Composite.Wpf.Regions
  24. {
  25. /// <summary>
  26. /// This class is responsible for maintaining a collection of regions and attaching regions to controls.
  27. /// </summary>
  28. /// <remarks>
  29. /// This class supplies the attached properties that can be used for simple region creation from XAML.
  30. /// It finds an adapter mapped to a WPF control and associates a new region to that control by calling
  31. /// <see cref="AttachNewRegion"/> automatically.
  32. /// </remarks>
  33. public class RegionManager : IRegionManager
  34. {
  35. #region Static properties (for XAML support)
  36. /// <summary>
  37. /// Identifies the RegionName attached property.
  38. /// </summary>
  39. /// <remarks>
  40. /// When a control has both the <see cref="RegionNameProperty"/> and
  41. /// <see cref="RegionManagerProperty"/> attached properties set to
  42. /// a value different than <see langword="null" /> and there is a
  43. /// <see cref="IRegionAdapter"/> mapping registered for the control, it
  44. /// will create and adapt a new region for that control, and register it
  45. /// in the <see cref="IRegionManager"/> with the specified region name.
  46. /// </remarks>
  47. public static readonly DependencyProperty RegionNameProperty = DependencyProperty.RegisterAttached(
  48. "RegionName",
  49. typeof(string),
  50. typeof(RegionManager),
  51. new PropertyMetadata(OnSetRegionNameCallback));
  52. /// <summary>
  53. /// Sets the <see cref="RegionNameProperty"/> attached property.
  54. /// </summary>
  55. /// <param name="regionTarget">The object to adapt. This is typically a container (i.e a control).</param>
  56. /// <param name="regionName">The name of the region to register.</param>
  57. public static void SetRegionName(DependencyObject regionTarget, string regionName)
  58. {
  59. regionTarget.SetValue(RegionNameProperty, regionName);
  60. }
  61. /// <summary>
  62. /// Gets the value for the <see cref="RegionNameProperty"/> attached property.
  63. /// </summary>
  64. /// <param name="regionTarget">The object to adapt. This is typically a container (i.e a control).</param>
  65. /// <returns>The name of the region that should be created when
  66. /// <see cref="RegionManagerProperty"/> is also set in this element.</returns>
  67. public static string GetRegionName(DependencyObject regionTarget)
  68. {
  69. return regionTarget.GetValue(RegionNameProperty) as string;
  70. }
  71. private static void OnSetRegionNameCallback(DependencyObject element, DependencyPropertyChangedEventArgs args)
  72. {
  73. if (element != null)
  74. {
  75. IRegionManager regionManager = element.GetValue(RegionManagerProperty) as IRegionManager;
  76. if (regionManager != null)
  77. {
  78. string oldRegionName = args.OldValue as string;
  79. if (oldRegionName != null)
  80. {
  81. regionManager.Regions.Remove(oldRegionName);
  82. }
  83. string newRegionName = args.NewValue as string;
  84. if (newRegionName != null)
  85. {
  86. regionManager.AttachNewRegion(element, newRegionName);
  87. }
  88. }
  89. }
  90. }
  91. /// <summary>
  92. /// Identifies the RegionManager attached property.
  93. /// </summary>
  94. /// <remarks>
  95. /// When a control has both the <see cref="RegionNameProperty"/> and
  96. /// <see cref="RegionManagerProperty"/> attached properties set to
  97. /// a value different than <see langword="null" /> and there is a
  98. /// <see cref="IRegionAdapter"/> mapping registered for the control, it
  99. /// will create and adapt a new region for that control, and register it
  100. /// in the <see cref="IRegionManager"/> with the specified region name.
  101. /// </remarks>
  102. public static readonly DependencyProperty RegionManagerProperty =
  103. DependencyProperty.RegisterAttached("RegionManager", typeof(IRegionManager), typeof(RegionManager),
  104. new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits, OnSetRegionManagerCallback));
  105. /// <summary>
  106. /// Gets the value of the <see cref="RegionNameProperty"/> attached property.
  107. /// </summary>
  108. /// <param name="target">The target element.</param>
  109. /// <returns>The <see cref="IRegionManager"/> attached to the <paramref name="target"/> element.</returns>
  110. public static IRegionManager GetRegionManager(DependencyObject target)
  111. {
  112. return (IRegionManager)target.GetValue(RegionManagerProperty);
  113. }
  114. /// <summary>
  115. /// Sets the <see cref="RegionManagerProperty"/> attached property.
  116. /// </summary>
  117. /// <param name="target">The target element.</param>
  118. /// <param name="value">The value.</param>
  119. public static void SetRegionManager(DependencyObject target, IRegionManager value)
  120. {
  121. target.SetValue(RegionManagerProperty, value);
  122. }
  123. private static void OnSetRegionManagerCallback(DependencyObject element, DependencyPropertyChangedEventArgs args)
  124. {
  125. if (element != null)
  126. {
  127. string regionName = element.GetValue(RegionNameProperty) as string;
  128. if (regionName != null)
  129. {
  130. IRegionManager oldRegionManager = args.OldValue as IRegionManager;
  131. if (oldRegionManager != null)
  132. {
  133. oldRegionManager.Regions.Remove(regionName);
  134. }
  135. IRegionManager newRegionManager = args.NewValue as IRegionManager;
  136. if (newRegionManager != null)
  137. {
  138. newRegionManager.AttachNewRegion(element, regionName);
  139. }
  140. }
  141. }
  142. }
  143. #endregion
  144. private readonly RegionAdapterMappings regionAdapterMappings;
  145. private readonly IDictionary<string, IRegion> _regions;
  146. /// <summary>
  147. /// Initializes a new instance of <see cref="RegionManager"/>.
  148. /// </summary>
  149. public RegionManager()
  150. {
  151. _regions = new RegionsDictionary(this);
  152. }
  153. /// <summary>
  154. /// Initializes a new instance of <see cref="RegionManager"/>.
  155. /// </summary>
  156. /// <param name="mappings">The <see cref="RegionAdapterMappings"/> that
  157. /// will be used when calling <see cref="AttachNewRegion"/> explicitly
  158. /// or by creating regions by using attached properties through XAML.
  159. /// </param>
  160. public RegionManager(RegionAdapterMappings mappings)
  161. : this()
  162. {
  163. this.regionAdapterMappings = mappings;
  164. }
  165. /// <summary>
  166. /// Gets a dictionary of <see cref="IRegion"/> that identify each region by name.
  167. /// You can use this dictionary to add or remove regions to the current region manager.
  168. /// </summary>
  169. /// <value>An <see cref="IDictionary{TKey,TValue}"/> with all the registered regions.</value>
  170. public IDictionary<string, IRegion> Regions
  171. {
  172. get { return _regions; }
  173. }
  174. /// <summary>
  175. /// Attaches a region to an object and adds it to the region manager.
  176. /// </summary>
  177. /// <param name="regionTarget">The object to adapt. This is typically a container (i.e a control).</param>
  178. /// <param name="regionName">The name of the region to register.</param>
  179. /// <exception cref="ArgumentException">When regions collection already has a region registered using <paramref name="regionName"/>.</exception>
  180. public void AttachNewRegion(object regionTarget, string regionName)
  181. {
  182. if (Regions.ContainsKey(regionName))
  183. throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, Resources.RegionNameExistsException, regionName));
  184. IRegionAdapter regionAdapter = regionAdapterMappings.GetMapping(regionTarget.GetType());
  185. IRegion region = regionAdapter.Initialize(regionTarget);
  186. Regions.Add(regionName, region);
  187. }
  188. /// <summary>
  189. /// Creates a new region manager.
  190. /// </summary>
  191. /// <returns>A new region manager that can be used as a different scope from the current region manager.</returns>
  192. public IRegionManager CreateRegionManager()
  193. {
  194. return new RegionManager(this.regionAdapterMappings);
  195. }
  196. class RegionsDictionary : Dictionary<string, IRegion>, IDictionary<string, IRegion>
  197. {
  198. private readonly IRegionManager regionManager;
  199. internal RegionsDictionary(IRegionManager regionManager)
  200. {
  201. this.regionManager = regionManager;
  202. }
  203. void IDictionary<string, IRegion>.Add(string key, IRegion value)
  204. {
  205. base.Add(key, value);
  206. value.RegionManager = regionManager;
  207. }
  208. bool IDictionary<string, IRegion>.Remove(string key)
  209. {
  210. bool removed = false;
  211. if (this.ContainsKey(key))
  212. {
  213. IRegion region = this[key];
  214. removed = base.Remove(key);
  215. region.RegionManager = null;
  216. }
  217. return removed;
  218. }
  219. }
  220. }
  221. }