示例#1
0
文件: Frame.cs 项目: JianwenSun/cc
        CustomJournalStateInternal IJournalState.GetJournalState(JournalReason journalReason)
        {
            if (journalReason != JournalReason.NewContentNavigation)
            {
                return null;
            }

            FramePersistState state = new FramePersistState();

            // Save a JournalEntry for the current content.
            state.JournalEntry = _navigationService.MakeJournalEntry(JournalReason.NewContentNavigation);
            // The current Content may be null or may not want to be journaled (=> JournalEntry=null).
            // But we still need to save and then restore the NS GUID - there may be other JEs keyed
            // by this GUID value.
            // i. There is a somewhat similar case in ApplicationProxyInternal._GetSaveHistoryBytesDelegate().
            state.NavSvcGuid = _navigationService.GuidId;

            state.JournalOwnership = _journalOwnership;
            if (_ownJournalScope != null)
            {
                Debug.Assert(_journalOwnership == JournalOwnership.OwnsJournal);
                // No need to make a copy here because this Frame object will be discarded.
                // (Supposedly the parent container is navigating away.)
                state.Journal = _ownJournalScope.Journal;
            }

            return state;
        }
 /// <summary>
 /// <see cref="IJournalState.GetJournalState"/>
 /// </summary>
 CustomJournalStateInternal IJournalState.GetJournalState(JournalReason journalReason)
 {
     int cp = -1;
     LogicalDirection cpDirection = LogicalDirection.Forward;
     TextPointer contentPosition = ContentPosition as TextPointer;
     if (contentPosition != null)
     {
         cp = contentPosition.Offset;
         cpDirection = contentPosition.LogicalDirection;
     }
     return new JournalState(cp, cpDirection, Zoom);
 }
示例#3
0
 private CustomJournalStateInternal GetRootViewerState(JournalReason journalReason)
 {
     if (_navigatorHostImpl != null && !(_bp is Visual))
     {
         Visual v = _navigatorHostImpl.FindRootViewer();
         IJournalState ijs = v as IJournalState;
         if (ijs != null)
         {
             return ijs.GetJournalState(journalReason);
         }
     }
     return null;
 }
示例#4
0
        /// <summary>
        /// Makes the appropriate kind of journal entry for the current Content and its state.
        /// For certain types of content, no journal entry is created (null is returned).
        /// </summary>
        internal JournalEntry MakeJournalEntry(JournalReason journalReason)
        {
            if (_bp == null)
            {
                return null;
            }

            Debug.Assert(_contentId != 0 &&
                (_journalEntryGroupState == null || _journalEntryGroupState.ContentId == _contentId));
            if (_journalEntryGroupState == null) // First journal entry created for the current Content?
            {
                _journalEntryGroupState = new JournalEntryGroupState(_guidId, _contentId);
            }

            JournalEntry journalEntry;
            bool keepAlive = IsContentKeepAlive();
            PageFunctionBase pfBase = _bp as PageFunctionBase;
            if (pfBase != null)
            {
                if (keepAlive)
                {
                    journalEntry = new JournalEntryPageFunctionKeepAlive(_journalEntryGroupState, pfBase);
                }
                else
                {
                    //
                    // If the PageFunction is navigated from xaml Uri, or navigated from an instance of
                    // PageFunction type, but that PageFunctin type is implemented from xaml file,
                    // we should always get the BaseUri DP value for the root PageFunction element.
                    //
                    // If the code navigates to pure #fragment, the root element should be ready,
                    // if the BaseUri for that root element is set, we should still use JournalEntryPageFunctionUri.
                    // if the BaseUri for that root element is not set, that pagefunction class is not
                    // implemented in xaml file, JournalEntryPageFunctionType is used for journaling.
                    // Navigation service has its own way to get to the element marked by the pure fragment.
                    //
                    Uri baseUri = pfBase.GetValue(BaseUriHelper.BaseUriProperty) as Uri;

                    if (baseUri != null)
                    {
                        Invariant.Assert(baseUri.IsAbsoluteUri == true, "BaseUri for root element should be absolute.");

                        Uri markupUri;

                        //
                        // Set correct uri when creating instance of JournalEntryPageFunctionUri
                        //
                        //   This markupUri is used to create instance of PageFunction from baml stream.
                        //   fragment in original Source doesn't affect the resource loading, and it will
                        //   be set in the JournalEntry.Source for further navigation handling. So the logic
                        //   of setting markupUri for JEPFUri can be simplified as below:
                        //
                        //   If _currentCleanSource is set and it is not a pure fragment uri, take whatever
                        //   value of _currentSource, which should always be an absolute Uri for the page.
                        //
                        //   For all other cases, take whatever value of BaseUri in root element.
                        //
                        if (_currentCleanSource != null && BindUriHelper.StartWithFragment(_currentCleanSource) == false )
                        {
                            markupUri = _currentSource;
                        }
                        else
                        {
                            markupUri = baseUri;
                        }

                        journalEntry = new JournalEntryPageFunctionUri(_journalEntryGroupState, pfBase, markupUri);
                    }
                    else
                    {
                        journalEntry = new JournalEntryPageFunctionType(_journalEntryGroupState, pfBase);
                    }
                }

                journalEntry.Source = _currentCleanSource; // This could be #fragment.
            }
            else
            {
                if (keepAlive)
                {
                    journalEntry = new JournalEntryKeepAlive(_journalEntryGroupState, _currentCleanSource, _bp);
                }
                else
                {
                    journalEntry = new JournalEntryUri(_journalEntryGroupState, _currentCleanSource);
                }
            }

            // _customContentStateToSave can be preset by AddBackEntry() or FireNavigating().
            // If not, try the IProvideCustomContentState callback.
            CustomContentState ccs = _customContentStateToSave;
            if (ccs == null)
            {
                IProvideCustomContentState pccs = _bp as IProvideCustomContentState;
                if (pccs != null)
                {
                    ccs = pccs.GetContentState();
                }
            }
            if (ccs != null)
            {
                // Make sure the object is serializable
                Type type = ccs.GetType();
                if (!type.IsSerializable)
                {
                    throw new SystemException(SR.Get(SRID.CustomContentStateMustBeSerializable, type));
                }
                journalEntry.CustomContentState = ccs;
            }
            // Info: CustomContentState for the current page in child frames is saved in
            // DataStreams.SaveState(). (This requires the IProvideCustomContentState to be implemented.)

            // Root Viewer journaling
            if (_rootViewerStateToSave != null) // state saved in advance?
            {
                journalEntry.RootViewerState = _rootViewerStateToSave;
                _rootViewerStateToSave = null;
            }
            else
            {
                journalEntry.RootViewerState = GetRootViewerState(journalReason);
            }

            // Set the friendly Name of this JournalEntry, it will be used to display
            // in the drop-down list on the Back/Forward buttons
            // Journal entries aren't recycled when going back\forward. A new JournalEntry is always created, so
            // we need to set the name each time
            // 

            string name = null;
            if (journalEntry.CustomContentState != null)
            {
                name = journalEntry.CustomContentState.JournalEntryName;
            }
            if (string.IsNullOrEmpty(name))
            {
                DependencyObject dependencyObject = _bp as DependencyObject;
                if (dependencyObject != null)
                {
                    name = (string)dependencyObject.GetValue(JournalEntry.NameProperty);

                    if (String.IsNullOrEmpty(name) && dependencyObject is Page)
                    {
                        name = (dependencyObject as Page).Title;
                    }
                }
                if (!String.IsNullOrEmpty(name))
                {
                    if (_currentSource != null)
                    {
                        string fragment = BindUriHelper.GetFragment(_currentSource);
                        if (!string.IsNullOrEmpty(fragment))
                        {
                            name = name + "#" + fragment;
                        }
                    }
                }
                else
                {
                    // Page.WindowTitle is just a shortcut to Window.Title.
                    // The window title is used as a journal entry name only for a top-level container.
                    NavigationWindow navWin =
                        JournalScope == null ? null : JournalScope.NavigatorHost as NavigationWindow;
                    if (navWin != null && this == navWin.NavigationService
                        && !String.IsNullOrEmpty(navWin.Title))
                    {
                        if (CurrentSource != null)
                        {
                            name = String.Format(CultureInfo.CurrentCulture, "{0} ({1})", navWin.Title, JournalEntry.GetDisplayName(_currentSource, SiteOfOriginContainer.SiteOfOrigin));
                        }
                        else
                        {
                            name = navWin.Title;
                        }
                    }
                    else
                    {
                        // if not title was set we use the uri if it is available.
                        if (CurrentSource != null)
                        {
                            name = JournalEntry.GetDisplayName(_currentSource, SiteOfOriginContainer.SiteOfOrigin);
                        }
                        else
                        {
                            name = SR.Get(SRID.Untitled);
                        }
                    }
                }
            }
            journalEntry.Name = name;

            if (journalReason == JournalReason.NewContentNavigation)
            {
                journalEntry.SaveState(_bp);
            }

            return journalEntry;
        }
示例#5
0
        private JournalEntry UpdateJournal(
            NavigationMode navigationMode, JournalReason journalReason, JournalEntry destinationJournalEntry)
        {
            Debug.Assert(navigationMode == NavigationMode.New ||
                navigationMode == NavigationMode.Back ||
                navigationMode == NavigationMode.Forward, "The journal should not be updated on Refresh.");
            // The point of this assert is that there should be no destinationJournalEntry for
            // navigationMode=New, but it is always required for Back/Fwd.
            Debug.Assert(destinationJournalEntry == null
                    ^ (navigationMode == NavigationMode.Back || navigationMode == NavigationMode.Forward));

            JournalEntry journalEntry = null;

            if (!_doNotJournalCurrentContent)
            {
                journalEntry = MakeJournalEntry(journalReason);
            }

            if (journalEntry == null)
            {
                _doNotJournalCurrentContent = false;

                // This case will be true when we have navigated to null and then gone back.  We cannot add null to the journal
                // but we still need to commit the back navigation to the journal so the journal state stays sane.
                if ((navigationMode == NavigationMode.Back || navigationMode == NavigationMode.Forward)
                    && JournalScope != null)
                {

                    JournalScope.Journal.CommitJournalNavigation(destinationJournalEntry);
                }
                // There's no need to do anything here for a New navigation.
                return null;
            }

            // EnsureJournal() should be called no earlier than here. Only the second navigation in a
            // NavigationService really requires a journal.
            // In particular, a child Frame should not be forced to create its own journal when it
            // is being re-navigated by DataStreams.Load(), because it doesn't yet have access to the
            // parent JournalNavigationScope.
            JournalNavigationScope journalScope = EnsureJournal();
            if (journalScope == null)
            {
                return null;
            }

            PageFunctionBase pfBase = _bp as PageFunctionBase;
            if (pfBase != null)
            {
                // PageFunctions that don't show UI don't get navigated to in the journal
                // We still need to add it to the journal since we need to resume this when its child finishes
                // This codepath is not executed if this pagefunction finished without launching a child.
                // That case is handled in HandleFinish

                if (navigationMode == NavigationMode.New && pfBase.Content == null)
                {
                    journalEntry.EntryType = JournalEntryType.UiLess;
                }
            }

            journalScope.Journal.UpdateCurrentEntry(journalEntry);

            if (journalEntry.IsNavigable())
            {
                CallUpdateTravelLog(navigationMode == NavigationMode.New);
            }

            if (navigationMode == NavigationMode.New)
            {
                journalScope.Journal.RecordNewNavigation();
            }
            else // Back or Forward
            {
                journalScope.Journal.CommitJournalNavigation(destinationJournalEntry);
            }

            _customContentStateToSave = null; // not needed anymore

            return journalEntry;
        }
示例#6
0
 /// <summary> 
 /// <see cref="IJournalState.GetJournalState"/>
 /// </summary> 
 CustomJournalStateInternal IJournalState.GetJournalState(JournalReason journalReason) 
 {
     int cp = -1; 
     LogicalDirection cpDirection = LogicalDirection.Forward;
     IFlowDocumentViewer viewer = CurrentViewer;
     if (viewer != null)
     { 
         TextPointer contentPosition = viewer.ContentPosition as TextPointer;
         if (contentPosition != null) 
         { 
             cp = contentPosition.Offset;
             cpDirection = contentPosition.LogicalDirection; 
         }
     }
     return new JournalState(cp, cpDirection, Zoom, ViewingMode);
 }