private void GoForwardBackCore(NavigationMode mode, bool canDoIt, Stack <JournalEntry> entries, string onFailureText)
        {
            if (canDoIt)
            {
                JournalEntry entry = entries.Peek();

                bool isFragmentNavigationOnly =
                    UriParsingHelper.InternalUriIsFragment(entry.Source) ||
                    UriParsingHelper.InternalUriGetAllButFragment(entry.Source) == UriParsingHelper.InternalUriGetAllButFragment(this._currentSourceAfterMapping);

                if (this.RaiseNavigating(entry.Source, mode, isFragmentNavigationOnly) == false)
                {
                    if (mode == NavigationMode.Back)
                    {
                        this.Journal.GoBack();
                    }
                    else
                    {
                        this.Journal.GoForward();
                    }
                }
                else
                {
                    this.RaiseNavigationStopped(null, entry.Source);
                }
            }
            else
            {
                Exception ex = new InvalidOperationException(onFailureText);
                if (this.RaiseNavigationFailed(null, ex))
                {
                    throw ex;
                }
            }
        }
        private void Initialize()
        {
            // Initialize stuff for the Uri template
            Regex newFromRegex = null;
            this._uriRegexIdentifierUsedTwice = this.UriTemplateContainsSameIdentifierTwice(this._uri, out newFromRegex);
            this._uriHasQueryString = !String.IsNullOrEmpty(UriParsingHelper.InternalUriGetQueryString(this._uri));
            this._uriHasFragment = !String.IsNullOrEmpty(UriParsingHelper.InternalUriGetFragment(this._uri));
            this._uriRegex = newFromRegex;
            this._mappedUriIsOnlyFragment = UriParsingHelper.InternalUriIsFragment(this._mappedUri);
            this._mappedUriIsOnlyQueryString = UriParsingHelper.QueryStringDelimiter + UriParsingHelper.InternalUriGetQueryString(this._mappedUri) == this._mappedUri.OriginalString;

            // Initialize stuff for the mapped Uri template
            this.GetIdentifiersForMappedUri(this._mappedUri);

            this._initialized = true;
        }
        private bool NavigateCore_StartNavigation(Uri uri, NavigationMode mode, bool suppressJournalAdd, Uri mergedUriAfterMapping, Uri mergedUri, bool isFragmentNavigationOnly)
        {
            this._currentNavigation = new NavigationOperation(mergedUriAfterMapping, mergedUri, uri, mode, suppressJournalAdd);

            if (isFragmentNavigationOnly)
            {
                // If we're navigating only to a fragment (e.g. "#frag2") then the Uri to journal should be that merged with the base uri
                if (UriParsingHelper.InternalUriIsFragment(uri))
                {
                    this._currentNavigation.UriForJournal = mergedUri;
                }
                this.Host.Dispatcher.BeginInvoke(() => this.CompleteNavigation(null));
                return(true);
            }

            this.UpdateNavigationCacheModeAlwaysPages();

            string uriAllButFragment = UriParsingHelper.InternalUriGetAllButFragment(uri);
            Page   reusedPage        = null;

            if (this._cacheRequiredPages.ContainsKey(uriAllButFragment))
            {
                reusedPage = this._cacheRequiredPages[uriAllButFragment];
            }
            else if (this.Cache.Contains(uriAllButFragment))
            {
                reusedPage = this.Cache[uriAllButFragment];
            }

            // If a page was found in either cache and that page hasn't yet changed its NavigationCacheMode to Disabled,
            // then navigation is done, otherwise open up new content
            if (reusedPage != null && reusedPage.NavigationCacheMode != NavigationCacheMode.Disabled)
            {
                this.Host.Dispatcher.BeginInvoke(() => this.CompleteNavigation(reusedPage));
            }
            else
            {
                this._currentNavigation.AsyncResult = this._contentLoader.BeginLoad(mergedUriAfterMapping, this._currentSourceAfterMapping, this.ContentLoader_BeginLoad_Callback, this._currentNavigation);
            }

            return(true);
        }
        private bool NavigateCore(Uri uri, NavigationMode mode, bool suppressJournalAdd, bool isRedirect)
        {
            try
            {
                if (uri == null)
                {
                    throw new ArgumentNullException("uri", Resource.NavigationService_NavigationToANullUriIsNotSupported);
                }

                // Make sure we're on the UI thread because of the DependencyProperties we use.
                if (!this.Host.Dispatcher.CheckAccess())
                {
                    // Move to UI thread
                    this.Host.Dispatcher.BeginInvoke(() => this.NavigateCore(uri, mode, suppressJournalAdd, isRedirect));
                    return(true);
                }

                Uri mappedUri = uri;
                // If the Uri is only a fragment, mapping does not take place
                if (!UriParsingHelper.InternalUriIsFragment(uri))
                {
                    UriMapperBase mapper = this.Host.UriMapper;
                    if (mapper != null)
                    {
                        Uri uriFromMapper = mapper.MapUri(uri);
                        if (uriFromMapper != null && !String.IsNullOrEmpty(uriFromMapper.OriginalString))
                        {
                            mappedUri = uriFromMapper;
                        }
                        else
                        {
                            mappedUri = uri;
                        }
                    }
                }

                Uri mergedUriAfterMapping = UriParsingHelper.InternalUriMerge(this._currentSourceAfterMapping, mappedUri) ?? mappedUri;
                Uri mergedUri             = UriParsingHelper.InternalUriMerge(this._currentSource, uri) ?? uri;

                // If we're navigating to just a fragment (i.e. "#frag1") or to a page which differs only in the fragment
                // (i.e. "Page.xaml?id=123" to "Page.xaml?id=123#frag1") then complete navigation without involving the content loader
                bool isFragmentNavigationOnly = (mode != NavigationMode.Refresh) &&
                                                (UriParsingHelper.InternalUriIsFragment(mappedUri) ||
                                                 UriParsingHelper.InternalUriGetAllButFragment(mergedUri) == UriParsingHelper.InternalUriGetAllButFragment(this._currentSource));

                // Check to see if anyone wants to cancel
                if (mode == NavigationMode.New || mode == NavigationMode.Refresh)
                {
                    if (this.RaiseNavigating(mergedUri, mode, isFragmentNavigationOnly) == true)
                    {
                        // Someone stopped us
                        this.RaiseNavigationStopped(null, mergedUri);
                        return(true);
                    }
                }

                // If the ContentLoader cannot load the new URI, throw an ArgumentException
                if (!this.ContentLoader.CanLoad(mappedUri, _currentSourceAfterMapping))
                {
                    throw new ArgumentException(Resource.NavigationService_CannotLoadUri, "uri");
                }

                if (isFragmentNavigationOnly && this.Host.Content == null)
                {
                    // It doesn't make sense to fragment navigate when there's no content, so raise NavigationFailed
                    throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture,
                                                                      Resource.NavigationService_FragmentNavigationRequiresContent,
                                                                      "Frame"));
                }

                if (isRedirect && this._currentNavigation != null &&
                    this._currentNavigation.UriForJournal == this._currentSource)
                {
                    // Do not record navigation in the journal in case of a redirection
                    // where the original target is the current URI.
                    suppressJournalAdd = true;
                }

                // Stop in-progress navigation
                this.StopLoadingCore(isRedirect);

                return(this.NavigateCore_StartNavigation(uri, mode, suppressJournalAdd, mergedUriAfterMapping, mergedUri, isFragmentNavigationOnly));
            }
            catch (Exception ex)
            {
                if (this.RaiseNavigationFailed(uri, ex))
                {
                    throw;
                }
                return(true);
            }
        }