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