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