Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / 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
- PrePrepareMethodAttribute.cs
- UdpMessageProperty.cs
- PolicyManager.cs
- HtmlDocument.cs
- URLBuilder.cs
- ResponseStream.cs
- PropertyTab.cs
- ExpressionVisitor.cs
- BindableAttribute.cs
- ArrayTypeMismatchException.cs
- CompositeTypefaceMetrics.cs
- SocketElement.cs
- StorageEntityTypeMapping.cs
- ApplicationManager.cs
- ApplicationFileParser.cs
- DataGridViewColumnConverter.cs
- DataGridViewElement.cs
- Size.cs
- ImageMetadata.cs
- AlignmentXValidation.cs
- WorkingDirectoryEditor.cs
- ConnectionProviderAttribute.cs
- PeerInvitationResponse.cs
- XPathParser.cs
- LiteralControl.cs
- AnnotationAuthorChangedEventArgs.cs
- Schema.cs
- AbandonedMutexException.cs
- SimpleHandlerBuildProvider.cs
- MessageEncodingBindingElementImporter.cs
- Timeline.cs
- SqlTrackingQuery.cs
- Line.cs
- PropertyOrder.cs
- columnmapkeybuilder.cs
- QuerySafeNavigator.cs
- SoapMessage.cs
- EntityClassGenerator.cs
- SetStoryboardSpeedRatio.cs
- ApplicationDirectory.cs
- StatusBarAutomationPeer.cs
- ActivityExecutionContext.cs
- _LazyAsyncResult.cs
- WindowsToolbarItemAsMenuItem.cs
- RemotingHelper.cs
- XmlAnyElementAttributes.cs
- SystemSounds.cs
- ConfigurationManagerInternal.cs
- HighlightComponent.cs
- ApplicationException.cs
- ConfigXmlSignificantWhitespace.cs
- Helpers.cs
- RegexStringValidatorAttribute.cs
- Literal.cs
- RecipientInfo.cs
- StringDictionary.cs
- ThreadStateException.cs
- XmlNotation.cs
- Environment.cs
- ReachIDocumentPaginatorSerializerAsync.cs
- EventLog.cs
- PreProcessInputEventArgs.cs
- HScrollBar.cs
- JulianCalendar.cs
- LocalizableAttribute.cs
- ExpressionEditorSheet.cs
- FilterException.cs
- FileStream.cs
- ServicePointManagerElement.cs
- IPPacketInformation.cs
- FlowDocumentReader.cs
- ImageListDesigner.cs
- CheckBox.cs
- PersonalizationState.cs
- ChainedAsyncResult.cs
- PropertyPathWorker.cs
- DataRecord.cs
- OleDbParameterCollection.cs
- EntityDataSourceDataSelection.cs
- EventTask.cs
- JournalEntryListConverter.cs
- PropertyRecord.cs
- EUCJPEncoding.cs
- PackageRelationshipSelector.cs
- StateDesigner.LayoutSelectionGlyph.cs
- TreeNodeSelectionProcessor.cs
- SynchronizedInputAdaptor.cs
- WebConvert.cs
- RepeaterItem.cs
- FunctionDescription.cs
- Menu.cs
- RefreshPropertiesAttribute.cs
- AppSettingsReader.cs
- ValidatorCompatibilityHelper.cs
- XmlTextReader.cs
- XPathMultyIterator.cs
- SiteMapProvider.cs
- InOutArgument.cs
- RuleSetDialog.Designer.cs
- TemplateInstanceAttribute.cs