/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
- //===================================================================================
- // Microsoft patterns & practices
- // Composite Application Guidance for Windows Presentation Foundation and Silverlight
- //===================================================================================
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
- // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
- // LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- // FITNESS FOR A PARTICULAR PURPOSE.
- //===================================================================================
- // The example companies, organizations, products, domain names,
- // e-mail addresses, logos, people, places, and events depicted
- // herein are fictitious. No association with any real company,
- // organization, product, domain name, email address, logo, person,
- // places, or events is intended or should be inferred.
- //===================================================================================
- using System;
- using System.ComponentModel;
- using System.Windows;
- using Microsoft.Practices.Composite.Presentation.Properties;
- using Microsoft.Practices.Composite.Regions;
-
- namespace Microsoft.Practices.Composite.Presentation.Regions.Behaviors
- {
- /// <summary>
- /// Subscribes to a static event from the <see cref="RegionManager"/> in order to register the target <see cref="IRegion"/>
- /// in a <see cref="IRegionManager"/> when one is available on the host control by walking up the tree and finding
- /// a control whose <see cref="RegionManager.RegionManagerProperty"/> property is not <see langword="null"/>.
- /// </summary>
- public class RegionManagerRegistrationBehavior : RegionBehavior, IHostAwareRegionBehavior
- {
- /// <summary>
- /// The key of this behavior.
- /// </summary>
- public static readonly string BehaviorKey = "RegionManagerRegistration";
-
- private WeakReference attachedRegionManagerWeakReference;
- private DependencyObject hostControl;
-
- /// <summary>
- /// Initializes a new instance of <see cref="RegionManagerRegistrationBehavior"/>.
- /// </summary>
- public RegionManagerRegistrationBehavior()
- {
- this.RegionManagerAccessor = new DefaultRegionManagerAccessor();
- }
-
- /// <summary>
- /// Provides an abstraction on top of the RegionManager static members.
- /// </summary>
- public IRegionManagerAccessor RegionManagerAccessor { get; set; }
-
- /// <summary>
- /// Gets or sets the <see cref="DependencyObject"/> that the <see cref="IRegion"/> is attached to.
- /// </summary>
- /// <value>A <see cref="DependencyObject"/> that the <see cref="IRegion"/> is attached to.
- /// This is usually a <see cref="FrameworkElement"/> that is part of the tree.</value>
- /// <exception cref="InvalidOperationException">When this member is set after the <see cref="IRegionBehavior.Attach"/> method has being called.</exception>
- public DependencyObject HostControl
- {
- get
- {
- return hostControl;
- }
- set
- {
- if (IsAttached)
- {
- throw new InvalidOperationException(Resources.HostControlCannotBeSetAfterAttach);
- }
- this.hostControl = value;
- }
- }
-
- /// <summary>
- /// When the <see cref="IRegion"/> has a name assigned, the behavior will start monitoring the ancestor controls in the element tree
- /// to look for an <see cref="IRegionManager"/> where to register the region in.
- /// </summary>
- protected override void OnAttach()
- {
- if (string.IsNullOrEmpty(this.Region.Name))
- {
- this.Region.PropertyChanged += this.Region_PropertyChanged;
- }
- else
- {
- this.StartMonitoringRegionManager();
- }
- }
-
- private void Region_PropertyChanged(object sender, PropertyChangedEventArgs e)
- {
- if (e.PropertyName == "Name" && !string.IsNullOrEmpty(this.Region.Name))
- {
- this.Region.PropertyChanged -= this.Region_PropertyChanged;
- this.StartMonitoringRegionManager();
- }
- }
-
- private void StartMonitoringRegionManager()
- {
- this.RegionManagerAccessor.UpdatingRegions += this.OnUpdatingRegions;
- this.TryRegisterRegion();
- }
-
- private void TryRegisterRegion()
- {
- DependencyObject targetElement = this.HostControl;
- if (targetElement.CheckAccess())
- {
- IRegionManager regionManager = this.FindRegionManager(targetElement);
-
- IRegionManager attachedRegionManager = this.GetAttachedRegionManager();
-
- if (regionManager != attachedRegionManager)
- {
- if (attachedRegionManager != null)
- {
- this.attachedRegionManagerWeakReference = null;
- attachedRegionManager.Regions.Remove(this.Region.Name);
- }
-
- if (regionManager != null)
- {
- this.attachedRegionManagerWeakReference = new WeakReference(regionManager);
-
- regionManager.Regions.Add(this.Region);
- }
- }
- }
- }
-
- /// <summary>
- /// This event handler gets called when a RegionManager is requering the instances of a region to be registered if they are not already.
- /// <remarks>Although this is a public method to support Weak Delegates in Silverlight, it should not be called by the user.</remarks>
- /// </summary>
- /// <param name="sender">The sender.</param>
- /// <param name="e">The arguments.</param>
- [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.")]
- public void OnUpdatingRegions(object sender, EventArgs e)
- {
- this.TryRegisterRegion();
- }
-
- private IRegionManager FindRegionManager(DependencyObject dependencyObject)
- {
- var regionmanager = this.RegionManagerAccessor.GetRegionManager(dependencyObject);
- if (regionmanager != null)
- {
- return regionmanager;
- }
-
- DependencyObject parent = null;
- #if SILVERLIGHT
- //parent = System.Windows.Media.VisualTreeHelper.GetParent(dependencyObject);
- FrameworkElement frameworkElement = dependencyObject as FrameworkElement;
- if (frameworkElement != null)
- {
- parent = frameworkElement.Parent;
- }
- #else
- parent = LogicalTreeHelper.GetParent(dependencyObject);
- #endif
- if (parent != null)
- {
- return this.FindRegionManager(parent);
- }
-
- return null;
- }
-
- private IRegionManager GetAttachedRegionManager()
- {
- if (this.attachedRegionManagerWeakReference != null)
- {
- return this.attachedRegionManagerWeakReference.Target as IRegionManager;
- }
-
- return null;
- }
- }
- }