PageRenderTime 25ms CodeModel.GetById 16ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 0ms

/V4/PrismLibrary/Desktop/Prism/Regions/RegionNavigationContentLoader.cs

#
C# | 150 lines | 79 code | 18 blank | 53 comment | 17 complexity | fc89782be2807438c0df8cf1cc255836 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.Collections.Generic;
 19using System.Globalization;
 20using System.Linq;
 21using System.Windows;
 22using Microsoft.Practices.Prism.Properties;
 23using Microsoft.Practices.ServiceLocation;
 24
 25namespace Microsoft.Practices.Prism.Regions
 26{
 27    /// <summary>
 28    /// Implementation of <see cref="IRegionNavigationContentLoader"/> that relies on a <see cref="IServiceLocator"/>
 29    /// to create new views when necessary.
 30    /// </summary>
 31    public class RegionNavigationContentLoader : IRegionNavigationContentLoader
 32    {
 33        private readonly IServiceLocator serviceLocator;
 34
 35        /// <summary>
 36        /// Initializes a new instance of the <see cref="RegionNavigationContentLoader"/> class with a service locator.
 37        /// </summary>
 38        /// <param name="serviceLocator">The service locator.</param>
 39        public RegionNavigationContentLoader(IServiceLocator serviceLocator)
 40        {
 41            this.serviceLocator = serviceLocator;
 42        }
 43
 44        /// <summary>
 45        /// Gets the view to which the navigation request represented by <paramref name="navigationContext"/> applies.
 46        /// </summary>
 47        /// <param name="region">The region.</param>
 48        /// <param name="navigationContext">The context representing the navigation request.</param>
 49        /// <returns>
 50        /// The view to be the target of the navigation request.
 51        /// </returns>
 52        /// <remarks>
 53        /// If none of the views in the region can be the target of the navigation request, a new view
 54        /// is created and added to the region.
 55        /// </remarks>
 56        /// <exception cref="ArgumentException">when a new view cannot be created for the navigation request.</exception>
 57        public object LoadContent(IRegion region, NavigationContext navigationContext)
 58        {
 59            if (region == null) throw new ArgumentNullException("region");
 60            if (navigationContext == null) throw new ArgumentNullException("navigationContext");
 61
 62            string candidateTargetContract = this.GetContractFromNavigationContext(navigationContext);
 63
 64            var candidates = this.GetCandidatesFromRegion(region, candidateTargetContract);
 65
 66            var acceptingCandidates =
 67                candidates.Where(
 68                    v =>
 69                    {
 70                        var navigationAware = v as INavigationAware;
 71                        if (navigationAware != null && !navigationAware.IsNavigationTarget(navigationContext))
 72                        {
 73                            return false;
 74                        }
 75
 76                        var frameworkElement = v as FrameworkElement;
 77                        if (frameworkElement == null)
 78                        {
 79                            return true;
 80                        }
 81
 82                        navigationAware = frameworkElement.DataContext as INavigationAware;
 83                        return navigationAware == null || navigationAware.IsNavigationTarget(navigationContext);
 84                    });
 85
 86
 87            var view = acceptingCandidates.FirstOrDefault();
 88
 89            if (view != null)
 90            {
 91                return view;
 92            }
 93
 94            view = this.CreateNewRegionItem(candidateTargetContract);
 95
 96            region.Add(view);
 97
 98            return view;
 99        }
100
101        /// <summary>
102        /// Provides a new item for the region based on the supplied candidate target contract name.
103        /// </summary>
104        /// <param name="candidateTargetContract">The target contract to build.</param>
105        /// <returns>An instance of an item to put into the <see cref="IRegion"/>.</returns>
106        protected virtual object CreateNewRegionItem(string candidateTargetContract)
107        {
108            object newRegionItem;
109            try
110            {           
111                newRegionItem = this.serviceLocator.GetInstance<object>(candidateTargetContract);
112            }
113            catch (ActivationException e)
114            {
115                throw new InvalidOperationException(
116                    string.Format(CultureInfo.CurrentCulture, Resources.CannotCreateNavigationTarget, candidateTargetContract),
117                    e);
118            }
119            return newRegionItem;
120        }
121
122        /// <summary>
123        /// Returns the candidate TargetContract based on the <see cref="NavigationContext"/>.
124        /// </summary>
125        /// <param name="navigationContext">The navigation contract.</param>
126        /// <returns>The candidate contract to seek within the <see cref="IRegion"/> and to use, if not found, when resolving from the container.</returns>
127        protected virtual string GetContractFromNavigationContext(NavigationContext navigationContext)
128        {
129            if (navigationContext == null) throw new ArgumentNullException("navigationContext");
130
131            var candidateTargetContract = UriParsingHelper.GetAbsolutePath(navigationContext.Uri);
132            candidateTargetContract = candidateTargetContract.TrimStart('/');
133            return candidateTargetContract;
134        }
135
136        /// <summary>
137        /// Returns the set of candidates that may satisfiy this navigation request.
138        /// </summary>
139        /// <param name="region">The region containing items that may satisfy the navigation request.</param>
140        /// <param name="candidateNavigationContract">The candidate navigation target as determined by <see cref="GetContractFromNavigationContext"/></param>
141        /// <returns>An enumerable of candidate objects from the <see cref="IRegion"/></returns>
142        protected virtual IEnumerable<object> GetCandidatesFromRegion(IRegion region, string candidateNavigationContract)
143        {
144            if (region == null) throw new ArgumentNullException("region");
145            return region.Views.Where(v =>
146                string.Equals(v.GetType().Name, candidateNavigationContract, StringComparison.Ordinal) ||
147                string.Equals(v.GetType().FullName, candidateNavigationContract, StringComparison.Ordinal));
148        }
149    }
150}