private void ContentLoader_BeginLoad_Callback(IAsyncResult result)
        {
            DependencyObject content = null;
            Uri uriBeingLoaded       = null;

            try
            {
                NavigationOperation asyncNavigationOperationCompleted = result.AsyncState as NavigationOperation;

                NavigationOperation navOp = this._currentNavigation;
                if (navOp == null || navOp.Uri != asyncNavigationOperationCompleted.Uri)
                {
                    // We already fired NavigationStopped in NavigateCore(), so just return without doing anything
                    return;
                }

                uriBeingLoaded = navOp.UriBeforeMapping;

                content = this._contentLoader.EndLoad(result) as DependencyObject;

                // If the content is anything but a UserControl, we should throw.
                // We support UserControls as they are a typical thing created in designers such as Blend,
                // but for a full experience one would use Page to get to things like NavigationContext,
                // NavigationService, Title, etc.
                if (!(content is UserControl))
                {
                    throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture,
                                                                      Resource.NavigationService_ContentIsNotAUserControl,
                                                                      content == null ? "null" : content.GetType().ToString(),
                                                                      "System.Windows.Controls.UserControl"));
                }

                // Content loader was successful, so complete navigation

                // Create a new navigation context
                JournalEntry.SetNavigationContext(content, new NavigationContext(UriParsingHelper.InternalUriParseQueryStringToDictionary(asyncNavigationOperationCompleted.Uri, true /* decodeResults */)));
                content.SetValue(NavigationServiceProperty, this);

                // Complete navigation operation
                this.CompleteNavigation(content);
            }
            catch (Exception ex)
            {
                if (this.RaiseNavigationFailed(uriBeingLoaded, ex))
                {
                    throw;
                }
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Attempts to process a Uri, if it matches the Uri template
        /// </summary>
        /// <param name="uri">The Uri to map</param>
        /// <returns>The Uri after mapping, or null if mapping did not succeed</returns>
        public Uri MapUri(Uri uri)
        {
            this.CheckPreconditions();

            if (this._uriRegex == null)
            {
                // If an empty Uri was passed in, we can map that even with an empty Uri Template.
                if (uri == null || uri.OriginalString == null || uri.OriginalString.Length == 0)
                {
                    return new Uri(this._mappedUri.OriginalString, UriKind.Relative);
                }
                // Otherwise, this does not match anything
                else
                {
                    return null;
                }
            }

            string originalUriWithoutQueryString = UriParsingHelper.InternalUriGetBaseValue(uri);

            Match m = this._uriRegex.Match(originalUriWithoutQueryString);

            if (!m.Success)
            {
                return null;
            }

            string uriAfterMappingBase = UriParsingHelper.InternalUriGetBaseValue(this._mappedUri);
            IDictionary<string, string> uriAfterMappingQueryString = UriParsingHelper.InternalUriParseQueryStringToDictionary(this._mappedUri, false /* decodeResults */);
            IDictionary<string, string> originalQueryString = UriParsingHelper.InternalUriParseQueryStringToDictionary(uri, false /* decodeResults */);
            string originalFragment = UriParsingHelper.InternalUriGetFragment(uri);
            string uriAfterMappingFragment = UriParsingHelper.InternalUriGetFragment(this._mappedUri);

            // 'uriValues' is the values of the identifiers from the 'Uri' template, as they appear in the Uri
            // being processed
            IDictionary<string, string> uriValues = new Dictionary<string, string>();

            // i begins at 1 because the group at index 0 is always equal to the parent's Match,
            // which we do not want.  We only want explicitly-named groups.
            int groupCount = m.Groups.Count;
            for (int i = 1; i < groupCount; i++)
            {
                uriValues.Add(this._uriRegex.GroupNameFromNumber(i), m.Groups[i].Value);
            }

            foreach (string identifier in this._mappedUriIdentifiers)
            {
                string identifierWithBraces = "{" + identifier + "}";
                string replacementValue = (uriValues.ContainsKey(identifier) ? uriValues[identifier] : String.Empty);

                // First check for identifiers in the base Uri, and replace them as appropriate
                uriAfterMappingBase = uriAfterMappingBase.Replace(identifierWithBraces, replacementValue);

                // Then, look through the query string (both the key and the value) and replace as appropriate
                string[] keys = new string[uriAfterMappingQueryString.Keys.Count];
                uriAfterMappingQueryString.Keys.CopyTo(keys, 0);
                foreach (string key in keys)
                {
                    // First check if the value contains it, as this is an easy replacement
                    if (uriAfterMappingQueryString[key].Contains(identifierWithBraces))
                    {
                        if (uriValues.ContainsKey(identifier))
                        {
                            uriAfterMappingQueryString[key] = uriAfterMappingQueryString[key].Replace(identifierWithBraces, replacementValue);
                        }
                    }

                    // If the key itself contains the identifier, then we need to remove the existing item with the key that
                    // contains the identifier, and re-add to the dictionary with the new key and the pre-existing value
                    if (key.Contains(identifierWithBraces))
                    {
                        string existingVal = uriAfterMappingQueryString[key];
                        uriAfterMappingQueryString.Remove(key);
                        uriAfterMappingQueryString.Add(key.Replace(identifierWithBraces, replacementValue), existingVal);
                    }
                }

                // If there's an original fragment already present, it will always win, so don't bother doing replacements
                if (String.IsNullOrEmpty(originalFragment) &&
                    !String.IsNullOrEmpty(uriAfterMappingFragment))
                {
                    if (uriAfterMappingFragment.Contains(identifierWithBraces))
                    {
                        uriAfterMappingFragment = uriAfterMappingFragment.Replace(identifierWithBraces, replacementValue);
                    }
                }
            }

            foreach (string key in originalQueryString.Keys)
            {
                if (!uriAfterMappingQueryString.ContainsKey(key))
                {
                    uriAfterMappingQueryString.Add(key, originalQueryString[key]);
                }
                else
                {
                    // If a value is present in the originally-navigated-to query string, it
                    // takes precedence over anything in the aliased query string by default.
                    uriAfterMappingQueryString[key] = originalQueryString[key];
                }
            }

            if (!String.IsNullOrEmpty(originalFragment))
            {
                uriAfterMappingFragment = originalFragment;
            }

            return UriParsingHelper.InternalUriCreateWithQueryStringValues(uriAfterMappingBase, uriAfterMappingQueryString, uriAfterMappingFragment);
        }