Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / MS / Internal / AppModel / JournalNavigationScope.cs / 1305600 / 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: [....] 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: [....] 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
- XsltOutput.cs
- PathFigureCollectionConverter.cs
- AssemblyUtil.cs
- ConditionalBranch.cs
- NodeLabelEditEvent.cs
- IdentityValidationException.cs
- ToolBarButtonClickEvent.cs
- HelpKeywordAttribute.cs
- HttpListener.cs
- HtmlInputCheckBox.cs
- WebPartDisplayModeEventArgs.cs
- xml.cs
- HttpChannelBindingToken.cs
- CodePrimitiveExpression.cs
- ExpressionNode.cs
- DefaultAuthorizationContext.cs
- HtmlWindow.cs
- HtmlMeta.cs
- DesignerTransaction.cs
- DbConnectionInternal.cs
- OdbcPermission.cs
- PnrpPeerResolver.cs
- Timeline.cs
- XPathAncestorQuery.cs
- DbInsertCommandTree.cs
- OdbcInfoMessageEvent.cs
- ReadOnlyDataSource.cs
- BulletedListEventArgs.cs
- ParameterCollection.cs
- MediaElementAutomationPeer.cs
- RegistrationServices.cs
- FastEncoderWindow.cs
- HttpListenerResponse.cs
- StreamReader.cs
- UriSectionData.cs
- ColorMatrix.cs
- oledbconnectionstring.cs
- MsmqIntegrationOutputChannel.cs
- ProfileGroupSettings.cs
- X509Chain.cs
- ForeignKeyConstraint.cs
- TreeNodeSelectionProcessor.cs
- OciEnlistContext.cs
- BeginEvent.cs
- RouteUrlExpressionBuilder.cs
- ControlIdConverter.cs
- MetadataArtifactLoaderComposite.cs
- MobileUserControlDesigner.cs
- RowBinding.cs
- designeractionlistschangedeventargs.cs
- SQLConvert.cs
- ValidationSummary.cs
- WindowsMenu.cs
- SelectionList.cs
- XmlSchemaObject.cs
- DataGridViewCellPaintingEventArgs.cs
- UriTemplateTrieLocation.cs
- InstancePersistenceCommand.cs
- TemplateBaseAction.cs
- TableCellCollection.cs
- ServiceMemoryGates.cs
- AssociationEndMember.cs
- MILUtilities.cs
- AuthorizationContext.cs
- ArgumentNullException.cs
- DataChangedEventManager.cs
- ExpressionVisitor.cs
- METAHEADER.cs
- CompatibleIComparer.cs
- ActionFrame.cs
- SubpageParaClient.cs
- SystemFonts.cs
- ApplicationContext.cs
- DoubleCollection.cs
- ScriptReferenceEventArgs.cs
- VectorKeyFrameCollection.cs
- PnrpPermission.cs
- IgnoreFileBuildProvider.cs
- InternalSafeNativeMethods.cs
- CriticalHandle.cs
- OleDbCommand.cs
- SmiContext.cs
- BamlResourceContent.cs
- Validator.cs
- cookieexception.cs
- BigInt.cs
- OleDbReferenceCollection.cs
- Rss20FeedFormatter.cs
- WebPartZoneBase.cs
- DBCSCodePageEncoding.cs
- SiteMembershipCondition.cs
- LogicalExpressionEditor.cs
- EntityDataSourceConfigureObjectContext.cs
- SchemaElementLookUpTable.cs
- VBCodeProvider.cs
- DataBoundLiteralControl.cs
- ListViewCancelEventArgs.cs
- TextRange.cs
- ListBoxChrome.cs
- TextServicesCompartment.cs