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

/V2.2/trunk/CAL/Desktop/Composite.Presentation/Regions/Behaviors/RegionManagerRegistrationBehavior.cs

#
C# | 182 lines | 116 code | 19 blank | 47 comment | 20 complexity | 7d48156e4b6780a58da23b3821113c12 MD5 | raw file
  1. //===================================================================================
  2. // Microsoft patterns & practices
  3. // Composite Application Guidance for Windows Presentation Foundation and Silverlight
  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.ComponentModel;
  19. using System.Windows;
  20. using Microsoft.Practices.Composite.Presentation.Properties;
  21. using Microsoft.Practices.Composite.Regions;
  22. namespace Microsoft.Practices.Composite.Presentation.Regions.Behaviors
  23. {
  24. /// <summary>
  25. /// Subscribes to a static event from the <see cref="RegionManager"/> in order to register the target <see cref="IRegion"/>
  26. /// in a <see cref="IRegionManager"/> when one is available on the host control by walking up the tree and finding
  27. /// a control whose <see cref="RegionManager.RegionManagerProperty"/> property is not <see langword="null"/>.
  28. /// </summary>
  29. public class RegionManagerRegistrationBehavior : RegionBehavior, IHostAwareRegionBehavior
  30. {
  31. /// <summary>
  32. /// The key of this behavior.
  33. /// </summary>
  34. public static readonly string BehaviorKey = "RegionManagerRegistration";
  35. private WeakReference attachedRegionManagerWeakReference;
  36. private DependencyObject hostControl;
  37. /// <summary>
  38. /// Initializes a new instance of <see cref="RegionManagerRegistrationBehavior"/>.
  39. /// </summary>
  40. public RegionManagerRegistrationBehavior()
  41. {
  42. this.RegionManagerAccessor = new DefaultRegionManagerAccessor();
  43. }
  44. /// <summary>
  45. /// Provides an abstraction on top of the RegionManager static members.
  46. /// </summary>
  47. public IRegionManagerAccessor RegionManagerAccessor { get; set; }
  48. /// <summary>
  49. /// Gets or sets the <see cref="DependencyObject"/> that the <see cref="IRegion"/> is attached to.
  50. /// </summary>
  51. /// <value>A <see cref="DependencyObject"/> that the <see cref="IRegion"/> is attached to.
  52. /// This is usually a <see cref="FrameworkElement"/> that is part of the tree.</value>
  53. /// <exception cref="InvalidOperationException">When this member is set after the <see cref="IRegionBehavior.Attach"/> method has being called.</exception>
  54. public DependencyObject HostControl
  55. {
  56. get
  57. {
  58. return hostControl;
  59. }
  60. set
  61. {
  62. if (IsAttached)
  63. {
  64. throw new InvalidOperationException(Resources.HostControlCannotBeSetAfterAttach);
  65. }
  66. this.hostControl = value;
  67. }
  68. }
  69. /// <summary>
  70. /// When the <see cref="IRegion"/> has a name assigned, the behavior will start monitoring the ancestor controls in the element tree
  71. /// to look for an <see cref="IRegionManager"/> where to register the region in.
  72. /// </summary>
  73. protected override void OnAttach()
  74. {
  75. if (string.IsNullOrEmpty(this.Region.Name))
  76. {
  77. this.Region.PropertyChanged += this.Region_PropertyChanged;
  78. }
  79. else
  80. {
  81. this.StartMonitoringRegionManager();
  82. }
  83. }
  84. private void Region_PropertyChanged(object sender, PropertyChangedEventArgs e)
  85. {
  86. if (e.PropertyName == "Name" && !string.IsNullOrEmpty(this.Region.Name))
  87. {
  88. this.Region.PropertyChanged -= this.Region_PropertyChanged;
  89. this.StartMonitoringRegionManager();
  90. }
  91. }
  92. private void StartMonitoringRegionManager()
  93. {
  94. this.RegionManagerAccessor.UpdatingRegions += this.OnUpdatingRegions;
  95. this.TryRegisterRegion();
  96. }
  97. private void TryRegisterRegion()
  98. {
  99. DependencyObject targetElement = this.HostControl;
  100. if (targetElement.CheckAccess())
  101. {
  102. IRegionManager regionManager = this.FindRegionManager(targetElement);
  103. IRegionManager attachedRegionManager = this.GetAttachedRegionManager();
  104. if (regionManager != attachedRegionManager)
  105. {
  106. if (attachedRegionManager != null)
  107. {
  108. this.attachedRegionManagerWeakReference = null;
  109. attachedRegionManager.Regions.Remove(this.Region.Name);
  110. }
  111. if (regionManager != null)
  112. {
  113. this.attachedRegionManagerWeakReference = new WeakReference(regionManager);
  114. regionManager.Regions.Add(this.Region);
  115. }
  116. }
  117. }
  118. }
  119. /// <summary>
  120. /// This event handler gets called when a RegionManager is requering the instances of a region to be registered if they are not already.
  121. /// <remarks>Although this is a public method to support Weak Delegates in Silverlight, it should not be called by the user.</remarks>
  122. /// </summary>
  123. /// <param name="sender">The sender.</param>
  124. /// <param name="e">The arguments.</param>
  125. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", Justification = "This has to be public in order to work with weak references in partial trust or Silverlight environments.")]
  126. public void OnUpdatingRegions(object sender, EventArgs e)
  127. {
  128. this.TryRegisterRegion();
  129. }
  130. private IRegionManager FindRegionManager(DependencyObject dependencyObject)
  131. {
  132. var regionmanager = this.RegionManagerAccessor.GetRegionManager(dependencyObject);
  133. if (regionmanager != null)
  134. {
  135. return regionmanager;
  136. }
  137. DependencyObject parent = null;
  138. #if SILVERLIGHT
  139. //parent = System.Windows.Media.VisualTreeHelper.GetParent(dependencyObject);
  140. FrameworkElement frameworkElement = dependencyObject as FrameworkElement;
  141. if (frameworkElement != null)
  142. {
  143. parent = frameworkElement.Parent;
  144. }
  145. #else
  146. parent = LogicalTreeHelper.GetParent(dependencyObject);
  147. #endif
  148. if (parent != null)
  149. {
  150. return this.FindRegionManager(parent);
  151. }
  152. return null;
  153. }
  154. private IRegionManager GetAttachedRegionManager()
  155. {
  156. if (this.attachedRegionManagerWeakReference != null)
  157. {
  158. return this.attachedRegionManagerWeakReference.Target as IRegionManager;
  159. }
  160. return null;
  161. }
  162. }
  163. }