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
- ListViewItemMouseHoverEvent.cs
- ConstNode.cs
- NullableFloatMinMaxAggregationOperator.cs
- CodeDirectoryCompiler.cs
- Translator.cs
- FileNotFoundException.cs
- PositiveTimeSpanValidatorAttribute.cs
- JapaneseLunisolarCalendar.cs
- FolderBrowserDialog.cs
- StateManagedCollection.cs
- PhysicalFontFamily.cs
- IpcClientChannel.cs
- InfoCardKeyedHashAlgorithm.cs
- ContentFileHelper.cs
- DBParameter.cs
- Empty.cs
- XpsDocument.cs
- SpeakProgressEventArgs.cs
- ConfigXmlComment.cs
- TableRowCollection.cs
- FixedHighlight.cs
- GlyphingCache.cs
- RightsManagementEncryptedStream.cs
- Header.cs
- TreeNodeBinding.cs
- IdentitySection.cs
- Timeline.cs
- WebPartChrome.cs
- CharStorage.cs
- ClientScriptItemCollection.cs
- SplineKeyFrames.cs
- ButtonChrome.cs
- EncryptedKey.cs
- SecurityManager.cs
- SemaphoreSecurity.cs
- XsltArgumentList.cs
- CharAnimationUsingKeyFrames.cs
- HandledEventArgs.cs
- WindowsListViewSubItem.cs
- BitmapMetadata.cs
- HtmlContainerControl.cs
- DataGridViewCellCancelEventArgs.cs
- BitmapPalettes.cs
- DbSource.cs
- CustomErrorsSection.cs
- CopyAttributesAction.cs
- SlotInfo.cs
- RSAProtectedConfigurationProvider.cs
- CacheMemory.cs
- MetadataSerializer.cs
- XmlNullResolver.cs
- OutputCacheSettingsSection.cs
- UInt32Storage.cs
- XmlObjectSerializerContext.cs
- NetTcpSectionData.cs
- ComplexBindingPropertiesAttribute.cs
- CategoryValueConverter.cs
- StreamReader.cs
- Visual3D.cs
- LineBreakRecord.cs
- NestedContainer.cs
- DecoratedNameAttribute.cs
- DataGridViewSelectedCellCollection.cs
- GridItemProviderWrapper.cs
- BinaryFormatterWriter.cs
- AuthenticationModuleElement.cs
- HTMLTagNameToTypeMapper.cs
- DragStartedEventArgs.cs
- LineMetrics.cs
- SocketException.cs
- MissingFieldException.cs
- GridSplitter.cs
- ParserHooks.cs
- MemoryFailPoint.cs
- Queue.cs
- DataGridViewColumnEventArgs.cs
- StateWorkerRequest.cs
- TextDecorationLocationValidation.cs
- TypedReference.cs
- Msmq4SubqueuePoisonHandler.cs
- EventPropertyMap.cs
- CodeMemberMethod.cs
- TreeNodeSelectionProcessor.cs
- RequestBringIntoViewEventArgs.cs
- ComponentSerializationService.cs
- RuntimeArgumentHandle.cs
- ObjectListTitleAttribute.cs
- ServiceOperationUIEditor.cs
- DataList.cs
- FlowLayout.cs
- SafeRightsManagementSessionHandle.cs
- ScrollData.cs
- _Rfc2616CacheValidators.cs
- List.cs
- CdpEqualityComparer.cs
- StaticContext.cs
- HtmlInputReset.cs
- BasicHttpBinding.cs
- DbUpdateCommandTree.cs
- PolyBezierSegment.cs