Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / Framework / MS / Internal / AppModel / JournalNavigationScope.cs / 1 / JournalNavigationScope.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // Description: // JournalNavigationScope is the entity that owns a Journal and handles or dispatches journaling- // related operations in a tree of navigators sharing the same journal. // NavigationWindow aggregates a JournalNavigationScope instance, as it always needs to have a // journal. So does Frame but only when its JournalOwnership=OwnsJournal. // JournalNavigationScope is not a standalone class. It delegate certain operations to its // "navigator host" via the IJournalNavigationScopeHost interface or directly to the host's // NavigationService. // // History: // 11/14/05: ChangoV Created; parts factored out of NavigationWindow. // //--------------------------------------------------------------------------- using System; using System.Collections; using System.Security; using System.Diagnostics; using System.Windows; using System.Windows.Navigation; using MS.Internal.KnownBoxes; namespace MS.Internal.AppModel { internal class JournalNavigationScope: DependencyObject, INavigator { internal JournalNavigationScope(IJournalNavigationScopeHost host) { _host = host; _rootNavSvc = host.NavigationService; } #region DependencyProperties // These properties are declared here, but actual values are set on NavigationWindow and Frame. // See OnBackForwardStateChange(). // CanGoBack & CanGoForward DPs private static readonly DependencyPropertyKey CanGoBackPropertyKey = DependencyProperty.RegisterReadOnly( "CanGoBack", typeof(bool), typeof(JournalNavigationScope), new FrameworkPropertyMetadata(BooleanBoxes.FalseBox)); internal static readonly DependencyProperty CanGoBackProperty = CanGoBackPropertyKey.DependencyProperty; private static readonly DependencyPropertyKey CanGoForwardPropertyKey = DependencyProperty.RegisterReadOnly( "CanGoForward", typeof(bool), typeof(JournalNavigationScope), new FrameworkPropertyMetadata(BooleanBoxes.FalseBox)); internal static readonly DependencyProperty CanGoForwardProperty = CanGoForwardPropertyKey.DependencyProperty; // BackStack & ForwardStack DPs private static readonly DependencyPropertyKey BackStackPropertyKey = DependencyProperty.RegisterReadOnly( "BackStack", typeof(IEnumerable), typeof(JournalNavigationScope), new FrameworkPropertyMetadata((IEnumerable)null)); internal static readonly DependencyProperty BackStackProperty = BackStackPropertyKey.DependencyProperty; private static readonly DependencyPropertyKey ForwardStackPropertyKey = DependencyProperty.RegisterReadOnly( "ForwardStack", typeof(IEnumerable), typeof(JournalNavigationScope), new FrameworkPropertyMetadata((IEnumerable)null)); internal static readonly DependencyProperty ForwardStackProperty = ForwardStackPropertyKey.DependencyProperty; #endregion DependencyProperties #region INavigatorBase Members public Uri Source { get { return _host.Source; } set { _host.Source = value; } } public Uri CurrentSource { get { return _host.CurrentSource; } } public object Content { get { return _host.Content; } set { _host.Content = value; } } public bool Navigate(Uri source) { return _host.Navigate(source); } public bool Navigate(Uri source, object extraData) { return _host.Navigate(source, extraData); } public bool Navigate(object content) { return _host.Navigate(content); } public bool Navigate(object content, object extraData) { return _host.Navigate(content, extraData); } public void StopLoading() { _host.StopLoading(); } public void Refresh() { _host.Refresh(); } public event NavigatingCancelEventHandler Navigating { add { _host.Navigating += value; } remove { _host.Navigating -= value; } } public event NavigationProgressEventHandler NavigationProgress { add { _host.NavigationProgress += value; } remove { _host.NavigationProgress -= value; } } public event NavigationFailedEventHandler NavigationFailed { add { _host.NavigationFailed += value; } remove { _host.NavigationFailed -= value; } } public event NavigatedEventHandler Navigated { add { _host.Navigated += value; } remove { _host.Navigated -= value; } } public event LoadCompletedEventHandler LoadCompleted { add { _host.LoadCompleted += value; } remove { _host.LoadCompleted -= value; } } public event NavigationStoppedEventHandler NavigationStopped { add { _host.NavigationStopped += value; } remove { _host.NavigationStopped -= value; } } public event FragmentNavigationEventHandler FragmentNavigation { add { _host.FragmentNavigation += value; } remove { _host.FragmentNavigation -= value; } } #endregion INavigatorBase #region INavigator Members // // Because the INavigator methods of NavigationWindow and Frame simply forward here, // _host.VerifyContextAndObjectState() should be called at every entry point. public bool CanGoForward { get { _host.VerifyContextAndObjectState(); return _journal != null && !InAppShutdown && _journal.CanGoForward; } } public bool CanGoBack { get { _host.VerifyContextAndObjectState(); return _journal != null && !InAppShutdown && _journal.CanGoBack; } } ////// Critical - calls RBW.GoForwardOverride, which is critical. /// Safe: We validate that you can only go back within your application. /// Note: SecurityTreatAsSafe is needed here because the method is effectively internal /// (INavigator is internal). It says 'public' because C# requires methods implementing /// interfaces to be public. /// [SecurityCritical, SecurityTreatAsSafe] public void GoForward() { // CanGoForward checks the calling thread and InAppShutdown as well if (CanGoForward == false) throw new InvalidOperationException(SR.Get(SRID.NoForwardEntry)); if (!_host.GoForwardOverride()) { JournalEntry je = Journal.BeginForwardNavigation(); // If je is null it indicates that we are going going "forward" to the currently // displayed page which has no journal entry. The comment in BeginForwardNavigation // explains how this can happen. if (je == null) { _rootNavSvc.StopLoading(); return; } NavigateToEntry(je); // NavigateToEntry() should call AbortJournalNavigation() if navigation is canceled. } } ////// Critical - calls RBW.GoBackOverride, which is critical. /// Safe: We validate that you can only go back within your application. /// [SecurityCritical, SecurityTreatAsSafe] public void GoBack() { // CanGoBack checks the calling thread and InAppShutdown as well if (CanGoBack == false) throw new InvalidOperationException(SR.Get(SRID.NoBackEntry)); if (!_host.GoBackOverride()) { JournalEntry je = Journal.BeginBackNavigation(); if (je == null) // See comment in GoForwardInternal(). { _rootNavSvc.StopLoading(); return; } NavigateToEntry(je); // NavigateToEntry() should call Journal.AbortJournalNavigation() if navigation is canceled. } } public void AddBackEntry(CustomContentState state) { _host.VerifyContextAndObjectState(); _rootNavSvc.AddBackEntry(state); } public JournalEntry RemoveBackEntry() { _host.VerifyContextAndObjectState(); return _journal == null ? null : _journal.RemoveBackEntry(); } public System.Collections.IEnumerable BackStack { get { _host.VerifyContextAndObjectState(); return Journal.BackStack; } } public System.Collections.IEnumerable ForwardStack { get { _host.VerifyContextAndObjectState(); return Journal.ForwardStack; } } JournalNavigationScope INavigator.GetJournal(bool create) { return this; } #endregion INavigator //----------------------------------------------------- // // Internal Methods // //----------------------------------------------------- #region Internal Methods ////// The Journal instance needs to be lazily-created to allow restoring a deserialized journal /// from the TravelLog or from a child Frame's journaled state (Frame.FramePersistState). /// Call this method to make the back stack and forward stack objects available and to allow /// anyone to register journal change event handlers. /// internal void EnsureJournal() { // The getter lazily creates Journal and notifies the host. Journal journal = Journal; Debug.Assert(journal != null); } internal bool CanInvokeJournalEntry(int entryId) { // _journal could be null for .deploy apps since the main (second) app is created after a delay // (the first app is created to show the progress UI and the main app is created when bits are ready) if (_journal == null) return false; int realIndex = _journal.FindIndexForEntryWithId(entryId); if (realIndex == -1) return false; JournalEntry entry = _journal[realIndex]; // Journal.IsNavigable() will apply the filter, which is normally IsEntryNavigable(). return _journal.IsNavigable(entry); } ////// Critical: causes a navigate /// TreatAsSafe: but only navigates to an existing entry in our journal, which is limited to the app. /// [SecurityCritical, SecurityTreatAsSafe] internal bool NavigateToEntry(int index) { JournalEntry entry = Journal[index]; return NavigateToEntry(entry); } internal bool NavigateToEntry(JournalEntry entry) { if (entry == null) { Debug.Fail("Tried to navigate to a null JournalEntry."); return false; } if (!Journal.IsNavigable(entry)) { Debug.Fail("Tried to navigate to a non-navigable journal entry."); return false; } NavigationService navigationService = _rootNavSvc.FindTarget(entry.NavigationServiceId); Debug.Assert(navigationService != null, "NavigationService cannot be null for journal navigations"); NavigationMode mode = Journal.GetNavigationMode(entry); bool navigated = false; try { navigated = entry.Navigate(navigationService.INavigatorHost, mode); } finally { if (!navigated) { AbortJournalNavigation(); } } return navigated; } internal void AbortJournalNavigation() { if (_journal != null) { _journal.AbortJournalNavigation(); } } internal INavigatorBase FindTarget(string name) { return _rootNavSvc.FindTarget(name); } internal static void ClearDPValues(DependencyObject navigator) { navigator.SetValue(CanGoBackPropertyKey, BooleanBoxes.FalseBox); navigator.SetValue(CanGoForwardPropertyKey, BooleanBoxes.FalseBox); navigator.SetValue(BackStackPropertyKey, null); navigator.SetValue(ForwardStackPropertyKey, null); } #if DEBUG ////// DO NOT USE - Public debug method to test the journal state for PageFunctions /// internal string PrintJournal() { Journal journal = Journal; String s = ""; for (int i = 0; i < journal.TotalCount; i++) { if (journal[i].IsNavigable()) { s += "o" ; } else { switch (journal[i].EntryType) { case JournalEntryType.Navigable: s += "o"; break; case JournalEntryType.UiLess: s += "u"; break; default: Invariant.Assert(false, "Invalid JournalEntryType: " + journal[i].EntryType); break; } } } return s; } #endif #endregion //------------------------------------------------------ // // Internal Properties // //----------------------------------------------------- #region Internal Properties ////// The Journal instance needs to be lazily-created to allow restoring a deserialized journal /// from the TravelLog or from a child Frame's journaled state (Frame.FramePersistState). /// The getter triggers the Journal creation and notifes the host. /// #if DEBUG // to prevent creating the Journal instance prematurely while debugging [DebuggerBrowsable(DebuggerBrowsableState.Never)] #endif internal Journal Journal { get { if (_journal == null) { Journal = new Journal(); } return _journal; } // Used by the getter; also by RootBrowserWindow and Frame to install a deserialized Journal. set { Debug.Assert(_journal == null && value != null, "The Journal should be set only once and never removed."); // see bug 1367999 _journal = value; _journal.Filter = new JournalEntryFilter(this.IsEntryNavigable); _journal.BackForwardStateChange += new EventHandler(OnBackForwardStateChange); DependencyObject navigator = (DependencyObject)_host; navigator.SetValue(BackStackPropertyKey, _journal.BackStack); navigator.SetValue(ForwardStackPropertyKey, _journal.ForwardStack); _host.OnJournalAvailable(); } } internal NavigationService RootNavigationService { get { return _rootNavSvc; } } internal INavigatorBase NavigatorHost { get { return _host; } } #endregion Internal Properties //------------------------------------------------------ // // Private Methods // //------------------------------------------------------ #region Private Methods private void OnBackForwardStateChange(object sender, EventArgs e) { Debug.Assert(sender == _journal); // Update CanGoBack and CanGoForward on the host navigator, only if actually changed. DependencyObject navigator = (DependencyObject)_host; bool canGoBackFwdChanged = false; bool newState = _journal.CanGoBack; if (newState != (bool)navigator.GetValue(CanGoBackProperty)) { navigator.SetValue(CanGoBackPropertyKey, BooleanBoxes.Box(newState)); canGoBackFwdChanged = true; } newState = _journal.CanGoForward; if (newState != (bool)navigator.GetValue(CanGoForwardProperty)) { navigator.SetValue(CanGoForwardPropertyKey, BooleanBoxes.Box(newState)); canGoBackFwdChanged = true; } if (canGoBackFwdChanged) { System.Windows.Input.CommandManager.InvalidateRequerySuggested(); } } ////// /// This is the filter callback for Journal. To keep a single code path and to avoid /// inconsistent results, use Journal.IsNavigable() instead of this method. /// private bool IsEntryNavigable(JournalEntry entry) { if (entry == null || !entry.IsNavigable()) return false; // If the entry is associated with a child frame, the frame has to be currently available. // For a given journal entry group, only the "exit" entry is made visible. Effectively, // this collapses all fragment-navigation and CustomContentState-navigation entries for // a page (other than the current one) to a single entry. That's what IE does. NavigationService ns = _rootNavSvc.FindTarget(entry.NavigationServiceId); return ns != null && (ns.ContentId == entry.ContentId || entry.JEGroupState.GroupExitEntry == entry); } private bool InAppShutdown { get { return System.Windows.Application.IsShuttingDown; } } #endregion //----------------------------------------------------- // // Private Fields // //------------------------------------------------------ #region Private Fields private IJournalNavigationScopeHost _host; private NavigationService _rootNavSvc; // == _host.NavigationService private Journal _journal; // lazily-created; see Journal property #endregion Private Fields }; ////// The interface through which JournalNavigationScope talks back to its navigator host. /// internal interface IJournalNavigationScopeHost: INavigatorBase { NavigationService NavigationService { get; } void VerifyContextAndObjectState(); void OnJournalAvailable(); ////// Allows the navigator host to do its own handling of GoBack. Currently used by /// RootBrowserWindow to do the TravelLog integration. /// ///True to cancel the normal handling of GoBack bool GoBackOverride(); bool GoForwardOverride(); }; } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // Description: // JournalNavigationScope is the entity that owns a Journal and handles or dispatches journaling- // related operations in a tree of navigators sharing the same journal. // NavigationWindow aggregates a JournalNavigationScope instance, as it always needs to have a // journal. So does Frame but only when its JournalOwnership=OwnsJournal. // JournalNavigationScope is not a standalone class. It delegate certain operations to its // "navigator host" via the IJournalNavigationScopeHost interface or directly to the host's // NavigationService. // // History: // 11/14/05: ChangoV Created; parts factored out of NavigationWindow. // //--------------------------------------------------------------------------- using System; using System.Collections; using System.Security; using System.Diagnostics; using System.Windows; using System.Windows.Navigation; using MS.Internal.KnownBoxes; namespace MS.Internal.AppModel { internal class JournalNavigationScope: DependencyObject, INavigator { internal JournalNavigationScope(IJournalNavigationScopeHost host) { _host = host; _rootNavSvc = host.NavigationService; } #region DependencyProperties // These properties are declared here, but actual values are set on NavigationWindow and Frame. // See OnBackForwardStateChange(). // CanGoBack & CanGoForward DPs private static readonly DependencyPropertyKey CanGoBackPropertyKey = DependencyProperty.RegisterReadOnly( "CanGoBack", typeof(bool), typeof(JournalNavigationScope), new FrameworkPropertyMetadata(BooleanBoxes.FalseBox)); internal static readonly DependencyProperty CanGoBackProperty = CanGoBackPropertyKey.DependencyProperty; private static readonly DependencyPropertyKey CanGoForwardPropertyKey = DependencyProperty.RegisterReadOnly( "CanGoForward", typeof(bool), typeof(JournalNavigationScope), new FrameworkPropertyMetadata(BooleanBoxes.FalseBox)); internal static readonly DependencyProperty CanGoForwardProperty = CanGoForwardPropertyKey.DependencyProperty; // BackStack & ForwardStack DPs private static readonly DependencyPropertyKey BackStackPropertyKey = DependencyProperty.RegisterReadOnly( "BackStack", typeof(IEnumerable), typeof(JournalNavigationScope), new FrameworkPropertyMetadata((IEnumerable)null)); internal static readonly DependencyProperty BackStackProperty = BackStackPropertyKey.DependencyProperty; private static readonly DependencyPropertyKey ForwardStackPropertyKey = DependencyProperty.RegisterReadOnly( "ForwardStack", typeof(IEnumerable), typeof(JournalNavigationScope), new FrameworkPropertyMetadata((IEnumerable)null)); internal static readonly DependencyProperty ForwardStackProperty = ForwardStackPropertyKey.DependencyProperty; #endregion DependencyProperties #region INavigatorBase Members public Uri Source { get { return _host.Source; } set { _host.Source = value; } } public Uri CurrentSource { get { return _host.CurrentSource; } } public object Content { get { return _host.Content; } set { _host.Content = value; } } public bool Navigate(Uri source) { return _host.Navigate(source); } public bool Navigate(Uri source, object extraData) { return _host.Navigate(source, extraData); } public bool Navigate(object content) { return _host.Navigate(content); } public bool Navigate(object content, object extraData) { return _host.Navigate(content, extraData); } public void StopLoading() { _host.StopLoading(); } public void Refresh() { _host.Refresh(); } public event NavigatingCancelEventHandler Navigating { add { _host.Navigating += value; } remove { _host.Navigating -= value; } } public event NavigationProgressEventHandler NavigationProgress { add { _host.NavigationProgress += value; } remove { _host.NavigationProgress -= value; } } public event NavigationFailedEventHandler NavigationFailed { add { _host.NavigationFailed += value; } remove { _host.NavigationFailed -= value; } } public event NavigatedEventHandler Navigated { add { _host.Navigated += value; } remove { _host.Navigated -= value; } } public event LoadCompletedEventHandler LoadCompleted { add { _host.LoadCompleted += value; } remove { _host.LoadCompleted -= value; } } public event NavigationStoppedEventHandler NavigationStopped { add { _host.NavigationStopped += value; } remove { _host.NavigationStopped -= value; } } public event FragmentNavigationEventHandler FragmentNavigation { add { _host.FragmentNavigation += value; } remove { _host.FragmentNavigation -= value; } } #endregion INavigatorBase #region INavigator Members // // Because the INavigator methods of NavigationWindow and Frame simply forward here, // _host.VerifyContextAndObjectState() should be called at every entry point. public bool CanGoForward { get { _host.VerifyContextAndObjectState(); return _journal != null && !InAppShutdown && _journal.CanGoForward; } } public bool CanGoBack { get { _host.VerifyContextAndObjectState(); return _journal != null && !InAppShutdown && _journal.CanGoBack; } } ////// Critical - calls RBW.GoForwardOverride, which is critical. /// Safe: We validate that you can only go back within your application. /// Note: SecurityTreatAsSafe is needed here because the method is effectively internal /// (INavigator is internal). It says 'public' because C# requires methods implementing /// interfaces to be public. /// [SecurityCritical, SecurityTreatAsSafe] public void GoForward() { // CanGoForward checks the calling thread and InAppShutdown as well if (CanGoForward == false) throw new InvalidOperationException(SR.Get(SRID.NoForwardEntry)); if (!_host.GoForwardOverride()) { JournalEntry je = Journal.BeginForwardNavigation(); // If je is null it indicates that we are going going "forward" to the currently // displayed page which has no journal entry. The comment in BeginForwardNavigation // explains how this can happen. if (je == null) { _rootNavSvc.StopLoading(); return; } NavigateToEntry(je); // NavigateToEntry() should call AbortJournalNavigation() if navigation is canceled. } } ////// Critical - calls RBW.GoBackOverride, which is critical. /// Safe: We validate that you can only go back within your application. /// [SecurityCritical, SecurityTreatAsSafe] public void GoBack() { // CanGoBack checks the calling thread and InAppShutdown as well if (CanGoBack == false) throw new InvalidOperationException(SR.Get(SRID.NoBackEntry)); if (!_host.GoBackOverride()) { JournalEntry je = Journal.BeginBackNavigation(); if (je == null) // See comment in GoForwardInternal(). { _rootNavSvc.StopLoading(); return; } NavigateToEntry(je); // NavigateToEntry() should call Journal.AbortJournalNavigation() if navigation is canceled. } } public void AddBackEntry(CustomContentState state) { _host.VerifyContextAndObjectState(); _rootNavSvc.AddBackEntry(state); } public JournalEntry RemoveBackEntry() { _host.VerifyContextAndObjectState(); return _journal == null ? null : _journal.RemoveBackEntry(); } public System.Collections.IEnumerable BackStack { get { _host.VerifyContextAndObjectState(); return Journal.BackStack; } } public System.Collections.IEnumerable ForwardStack { get { _host.VerifyContextAndObjectState(); return Journal.ForwardStack; } } JournalNavigationScope INavigator.GetJournal(bool create) { return this; } #endregion INavigator //----------------------------------------------------- // // Internal Methods // //----------------------------------------------------- #region Internal Methods ////// The Journal instance needs to be lazily-created to allow restoring a deserialized journal /// from the TravelLog or from a child Frame's journaled state (Frame.FramePersistState). /// Call this method to make the back stack and forward stack objects available and to allow /// anyone to register journal change event handlers. /// internal void EnsureJournal() { // The getter lazily creates Journal and notifies the host. Journal journal = Journal; Debug.Assert(journal != null); } internal bool CanInvokeJournalEntry(int entryId) { // _journal could be null for .deploy apps since the main (second) app is created after a delay // (the first app is created to show the progress UI and the main app is created when bits are ready) if (_journal == null) return false; int realIndex = _journal.FindIndexForEntryWithId(entryId); if (realIndex == -1) return false; JournalEntry entry = _journal[realIndex]; // Journal.IsNavigable() will apply the filter, which is normally IsEntryNavigable(). return _journal.IsNavigable(entry); } ////// Critical: causes a navigate /// TreatAsSafe: but only navigates to an existing entry in our journal, which is limited to the app. /// [SecurityCritical, SecurityTreatAsSafe] internal bool NavigateToEntry(int index) { JournalEntry entry = Journal[index]; return NavigateToEntry(entry); } internal bool NavigateToEntry(JournalEntry entry) { if (entry == null) { Debug.Fail("Tried to navigate to a null JournalEntry."); return false; } if (!Journal.IsNavigable(entry)) { Debug.Fail("Tried to navigate to a non-navigable journal entry."); return false; } NavigationService navigationService = _rootNavSvc.FindTarget(entry.NavigationServiceId); Debug.Assert(navigationService != null, "NavigationService cannot be null for journal navigations"); NavigationMode mode = Journal.GetNavigationMode(entry); bool navigated = false; try { navigated = entry.Navigate(navigationService.INavigatorHost, mode); } finally { if (!navigated) { AbortJournalNavigation(); } } return navigated; } internal void AbortJournalNavigation() { if (_journal != null) { _journal.AbortJournalNavigation(); } } internal INavigatorBase FindTarget(string name) { return _rootNavSvc.FindTarget(name); } internal static void ClearDPValues(DependencyObject navigator) { navigator.SetValue(CanGoBackPropertyKey, BooleanBoxes.FalseBox); navigator.SetValue(CanGoForwardPropertyKey, BooleanBoxes.FalseBox); navigator.SetValue(BackStackPropertyKey, null); navigator.SetValue(ForwardStackPropertyKey, null); } #if DEBUG ////// DO NOT USE - Public debug method to test the journal state for PageFunctions /// internal string PrintJournal() { Journal journal = Journal; String s = ""; for (int i = 0; i < journal.TotalCount; i++) { if (journal[i].IsNavigable()) { s += "o" ; } else { switch (journal[i].EntryType) { case JournalEntryType.Navigable: s += "o"; break; case JournalEntryType.UiLess: s += "u"; break; default: Invariant.Assert(false, "Invalid JournalEntryType: " + journal[i].EntryType); break; } } } return s; } #endif #endregion //------------------------------------------------------ // // Internal Properties // //----------------------------------------------------- #region Internal Properties ////// The Journal instance needs to be lazily-created to allow restoring a deserialized journal /// from the TravelLog or from a child Frame's journaled state (Frame.FramePersistState). /// The getter triggers the Journal creation and notifes the host. /// #if DEBUG // to prevent creating the Journal instance prematurely while debugging [DebuggerBrowsable(DebuggerBrowsableState.Never)] #endif internal Journal Journal { get { if (_journal == null) { Journal = new Journal(); } return _journal; } // Used by the getter; also by RootBrowserWindow and Frame to install a deserialized Journal. set { Debug.Assert(_journal == null && value != null, "The Journal should be set only once and never removed."); // see bug 1367999 _journal = value; _journal.Filter = new JournalEntryFilter(this.IsEntryNavigable); _journal.BackForwardStateChange += new EventHandler(OnBackForwardStateChange); DependencyObject navigator = (DependencyObject)_host; navigator.SetValue(BackStackPropertyKey, _journal.BackStack); navigator.SetValue(ForwardStackPropertyKey, _journal.ForwardStack); _host.OnJournalAvailable(); } } internal NavigationService RootNavigationService { get { return _rootNavSvc; } } internal INavigatorBase NavigatorHost { get { return _host; } } #endregion Internal Properties //------------------------------------------------------ // // Private Methods // //------------------------------------------------------ #region Private Methods private void OnBackForwardStateChange(object sender, EventArgs e) { Debug.Assert(sender == _journal); // Update CanGoBack and CanGoForward on the host navigator, only if actually changed. DependencyObject navigator = (DependencyObject)_host; bool canGoBackFwdChanged = false; bool newState = _journal.CanGoBack; if (newState != (bool)navigator.GetValue(CanGoBackProperty)) { navigator.SetValue(CanGoBackPropertyKey, BooleanBoxes.Box(newState)); canGoBackFwdChanged = true; } newState = _journal.CanGoForward; if (newState != (bool)navigator.GetValue(CanGoForwardProperty)) { navigator.SetValue(CanGoForwardPropertyKey, BooleanBoxes.Box(newState)); canGoBackFwdChanged = true; } if (canGoBackFwdChanged) { System.Windows.Input.CommandManager.InvalidateRequerySuggested(); } } ////// /// This is the filter callback for Journal. To keep a single code path and to avoid /// inconsistent results, use Journal.IsNavigable() instead of this method. /// private bool IsEntryNavigable(JournalEntry entry) { if (entry == null || !entry.IsNavigable()) return false; // If the entry is associated with a child frame, the frame has to be currently available. // For a given journal entry group, only the "exit" entry is made visible. Effectively, // this collapses all fragment-navigation and CustomContentState-navigation entries for // a page (other than the current one) to a single entry. That's what IE does. NavigationService ns = _rootNavSvc.FindTarget(entry.NavigationServiceId); return ns != null && (ns.ContentId == entry.ContentId || entry.JEGroupState.GroupExitEntry == entry); } private bool InAppShutdown { get { return System.Windows.Application.IsShuttingDown; } } #endregion //----------------------------------------------------- // // Private Fields // //------------------------------------------------------ #region Private Fields private IJournalNavigationScopeHost _host; private NavigationService _rootNavSvc; // == _host.NavigationService private Journal _journal; // lazily-created; see Journal property #endregion Private Fields }; ////// The interface through which JournalNavigationScope talks back to its navigator host. /// internal interface IJournalNavigationScopeHost: INavigatorBase { NavigationService NavigationService { get; } void VerifyContextAndObjectState(); void OnJournalAvailable(); ////// Allows the navigator host to do its own handling of GoBack. Currently used by /// RootBrowserWindow to do the TravelLog integration. /// ///True to cancel the normal handling of GoBack bool GoBackOverride(); bool GoForwardOverride(); }; } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ArraySegment.cs
- AnimatedTypeHelpers.cs
- PeerResolverBindingElement.cs
- DrawingContextDrawingContextWalker.cs
- SkewTransform.cs
- MailDefinition.cs
- ThreadPool.cs
- Assert.cs
- SystemTcpStatistics.cs
- ComplexType.cs
- SubMenuStyleCollection.cs
- StylusDownEventArgs.cs
- HttpHandlerAction.cs
- UnsafeNativeMethods.cs
- CodeTypeReferenceExpression.cs
- MenuBase.cs
- RsaSecurityKey.cs
- PrimarySelectionAdorner.cs
- XmlNamespaceDeclarationsAttribute.cs
- TranslateTransform.cs
- EditModeSwitchButton.cs
- DuplexChannelBinder.cs
- OleDbWrapper.cs
- TimeoutValidationAttribute.cs
- EditorServiceContext.cs
- ResponseBodyWriter.cs
- CalculatedColumn.cs
- TreeNodeStyle.cs
- WizardPanel.cs
- PeerNameRegistration.cs
- WaitForChangedResult.cs
- ChangeBlockUndoRecord.cs
- JumpPath.cs
- ApplicationInterop.cs
- ImageSource.cs
- BindingContext.cs
- DataGridViewDesigner.cs
- SimpleRecyclingCache.cs
- ListViewItemMouseHoverEvent.cs
- LayoutManager.cs
- TextBoxAutoCompleteSourceConverter.cs
- AuthenticationService.cs
- RunInstallerAttribute.cs
- SiteMapDataSource.cs
- SystemWebCachingSectionGroup.cs
- DynamicRenderer.cs
- ToolStripGripRenderEventArgs.cs
- DecimalStorage.cs
- DbSourceParameterCollection.cs
- XmlArrayAttribute.cs
- ContentHostHelper.cs
- MsmqException.cs
- MaskedTextProvider.cs
- ColorConverter.cs
- ConnectionPointGlyph.cs
- TextFormatterContext.cs
- RSAOAEPKeyExchangeDeformatter.cs
- SafeArchiveContext.cs
- CharEnumerator.cs
- TextRange.cs
- HwndSourceKeyboardInputSite.cs
- WebBrowser.cs
- AliasGenerator.cs
- ContextMenu.cs
- RightsManagementEncryptionTransform.cs
- HtmlControl.cs
- HttpVersion.cs
- Floater.cs
- EntityDataSource.cs
- TemplateBindingExtensionConverter.cs
- CompilationRelaxations.cs
- MatrixStack.cs
- EncodingInfo.cs
- EventManager.cs
- PropertyNames.cs
- PeerNameRecord.cs
- CopyAttributesAction.cs
- CellLabel.cs
- DependencyStoreSurrogate.cs
- XPathDocumentIterator.cs
- TabControlEvent.cs
- DataServiceConfiguration.cs
- TextRangeAdaptor.cs
- ArraySet.cs
- DecoratedNameAttribute.cs
- SafeCryptoHandles.cs
- RegexBoyerMoore.cs
- StreamedWorkflowDefinitionContext.cs
- ContextBase.cs
- HostSecurityManager.cs
- PageThemeCodeDomTreeGenerator.cs
- ObfuscationAttribute.cs
- BooleanStorage.cs
- SQLChars.cs
- PtsPage.cs
- SelectionListDesigner.cs
- SynchronizationContext.cs
- CSharpCodeProvider.cs
- SmtpNegotiateAuthenticationModule.cs
- DataTableReaderListener.cs