Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / System / Windows / Controls / Frame.cs / 1 / Frame.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // Description: // Frame is a ContentControl with navigation and journaling capabilities, much like NavigationWindow. // It can use its own journal ("island frame") or its prent's, if available. // // History: // ?? ?? Created // 11/14/05: [....] "Island Frame" implementation: Frame can have its own Journal/JournalNavigationScope. // //--------------------------------------------------------------------------- using System; using System.Net; using System.Collections; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.Windows.Threading; using System.Security; using System.Windows; using System.Windows.Input; using System.Windows.Automation.Peers; using System.Windows.Media; using System.Windows.Navigation; using System.Windows.Markup; using MS.Internal; using MS.Internal.AppModel; using MS.Internal.Utility; using MS.Internal.KnownBoxes; using MS.Utility; using MS.Internal.Controls; using MS.Internal.PresentationFramework; using System.Collections.Generic; namespace System.Windows.Navigation { ////// Journaling options for Frame /// [Serializable] public enum JournalOwnership { ////// Whether or not this Frame will create and use its own journal depends on its parent. /// If the Frame is hosted by another Frame or a NavigationWindow, it behaves as though /// UseParentJournal was set. If it is not hosted by a Frame or NavigationWindow or all /// containing frames have the UsesParentJournal setting, this frame will use its own journal. /// Once a frame creates its own journal, switching to Automatic has no effect. /// Automatic = 0, ////// The Frame has its own Journal which operates independent of the hosting container�s /// journal (if it has one). /// OwnsJournal, ////// The Frame�s journal entries are merged into the hosting container�s journal, if available. /// Otherwise navigations in this frame are not journaled. /// UsesParentJournal }; ////// public enum NavigationUIVisibility { ////// The navigation UI is visible when Frame has its own journal. /// Automatic = 0, ////// Visible, ////// Hidden }; } namespace System.Windows.Controls { ////// Frame control is an area that is used for loading a tree of elements. /// It uses the application navigation model to populate its content. /// Hence its content model is dictated solely by the NavigationService it aggregates which has /// a Uri property that points to the Uri of the page that is to be loaded into the Frame. /// There is also a Content property that returns the root element of the Framework tree being loaded from the Uri. /// It is also possible to create a tree for the Frames content programmatically and set the Content property to it. /// [DefaultProperty("Source"), DefaultEvent("Navigated")] [Localizability(LocalizationCategory.Ignore)] #if OLD_AUTOMATION [Automation(AccessibilityControlType = "Window")] #endif [ContentProperty] [TemplatePart(Name = "PART_FrameCP", Type = typeof(ContentPresenter))] public class Frame : ContentControl, INavigator, INavigatorImpl, IJournalNavigationScopeHost, IDownloader, IJournalState, IAddChild, IUriContext { #region Constructors ////// Default constructor /// ////// Automatic determination of current Dispatcher. Use alternative constructor /// that accepts a Dispatcher for best performance. /// public Frame() : base() { Init(); } static Frame() { DefaultStyleKeyProperty.OverrideMetadata(typeof(Frame), new FrameworkPropertyMetadata(typeof(Frame))); _dType = DependencyObjectType.FromSystemTypeInternal(typeof(Frame)); ContentProperty.OverrideMetadata( typeof(Frame), new FrameworkPropertyMetadata( null, new CoerceValueCallback(CoerceContent))); KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(Frame), new FrameworkPropertyMetadata(KeyboardNavigationMode.Local)); KeyboardNavigation.ControlTabNavigationProperty.OverrideMetadata(typeof(Frame), new FrameworkPropertyMetadata(KeyboardNavigationMode.Once)); NavigationService.NavigationServiceProperty.OverrideMetadata( typeof(Frame), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnParentNavigationServiceChanged))); } private static object CoerceContent(DependencyObject d, object value) { // whenever content changes, defer the change until the Navigate comes in Frame f = (Frame) d; if (f._navigationService.Content == value) { return value; } f.Navigate(value); return DependencyProperty.UnsetValue; } ////// Initialize /// private void Init() { InheritanceBehavior = InheritanceBehavior.SkipToAppNow; ContentIsNotLogical = true; _navigationService = new NavigationService(this); _navigationService.BPReady += new BPReadyEventHandler(_OnBPReady); } #endregion #region IUriContext implementation ////// Accessor for the base uri of the frame /// Uri IUriContext.BaseUri { get { return BaseUri; } set { BaseUri = value; } } ////// Implementation for BaseUri /// protected virtual Uri BaseUri { get { return (Uri)GetValue(BaseUriHelper.BaseUriProperty); } set { SetValue(BaseUriHelper.BaseUriProperty, value); } } #endregion IUriContext implementation #region IDownloader implementation NavigationService IDownloader.Downloader { get { return _navigationService; } } ////// Rasied when Content is rendered and ready for user interaction. /// public event EventHandler ContentRendered; ////// This override fires the ContentRendered event. /// /// protected virtual void OnContentRendered(EventArgs args) { // After the content is rendered we want to check if there is an element that needs to be focused // If there is - set focus to it DependencyObject doContent = Content as DependencyObject; if (doContent != null) { IInputElement focusedElement = FocusManager.GetFocusedElement(doContent) as IInputElement; if (focusedElement != null) focusedElement.Focus(); } if (ContentRendered != null) { ContentRendered(this, args); } } #endregion IDownloader implementation #region Properties ////// /// public static readonly DependencyProperty SourceProperty = DependencyProperty.Register( "Source", typeof(Uri), typeof(Frame), new FrameworkPropertyMetadata( (Uri) null, // The Journal flag tells the parser not to re-assign the property // when doing journal navigation. See ParserContext.SkipJournaledProperties. FrameworkPropertyMetadataOptions.Journal, new PropertyChangedCallback(OnSourcePropertyChanged), new CoerceValueCallback(CoerceSource))); private static object CoerceSource(DependencyObject d, object value) { Frame frame = (Frame)d; // If the Source property is coerced from NavService as a result of navigation, not from other // source, e.g, SetValue, DataBinding, Style..., we should use NavService.Source. if (frame._sourceUpdatedFromNavService) { Invariant.Assert(frame._navigationService != null, "_navigationService should never be null here"); // Turn this Assert on after fix the issue that NavService.Source is not absolute for SiteOfOrigin. //Invariant.Assert(frame._navigationService.Source != null ? !frame._navigationService.Source.IsAbsoluteUri : true, "NavService's Source should always be relative"); return frame._navigationService.Source; } return value; } ////// Called when SourceProperty is invalidated on 'd' /// ////// Critical as it access the base uri through GetUriToNavigate /// TreatAsSafe since it does not disclose this /// [SecurityCritical, SecurityTreatAsSafe] private static void OnSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { Frame frame = (Frame)d; // Don't navigate if the Source value change is from NavService as a result of a navigation happening. if (! frame._sourceUpdatedFromNavService) { // We used to unhook first visual child here. // Since we enabled styling for Frame. We're relying on Content property and ContentPresenter in Frame's style // to add/remove content from VisualTree. Uri uriToNavigate = BindUriHelper.GetUriToNavigate(frame, ((IUriContext)frame).BaseUri, (Uri)e.NewValue); // Calling the internal Navigate from Frame and NavWin's Source DP's property changed callbacks // We would not set value back in this case. frame._navigationService.Navigate(uriToNavigate, null, false, true/* navigateOnSourceChanged */); } } // This method is called from NavService whenever the NavService's Source value is updated. // The INavigator uses this to update its SourceProperty. // It indicates whether the NavService's Source value is as a result of // calling Navigate API directly or from GoBack/GoForward, journal navigation, a cancellation void INavigatorImpl.OnSourceUpdatedFromNavService(bool journalOrCancel) { _sourceUpdatedFromNavService = true; try { // If the Source DP is not set locally, or it is expression/animation, // we do not want to SetValue on it when it is from GoBack/GoForward, journal navigation or cancel. // Only when it comes from calling Navigate API directly we consider it has the same pri as SetValue. if (journalOrCancel) { bool hasModifiers, isExpression, isAnimated, isCoerced; BaseValueSourceInternal valueSource = GetValueSource(SourceProperty, null, out hasModifiers, out isExpression, out isAnimated, out isCoerced); if ((valueSource != BaseValueSourceInternal.Local) || isExpression || isAnimated) { CoerceValue(SourceProperty); return; } } SetValue(SourceProperty, _navigationService.Source); } finally { _sourceUpdatedFromNavService = false; } } ////// URI to navigate to. /// [Bindable(true), CustomCategory("Navigation")] public Uri Source { get { return (Uri) GetValue(SourceProperty); } set { SetValue(SourceProperty, value); } } ////// The DependencyProperty for the CanGoBack property. /// Flags: None /// Default Value: false /// Readonly: true /// public static readonly DependencyProperty CanGoBackProperty = JournalNavigationScope.CanGoBackProperty.AddOwner(typeof(Frame)); ////// The DependencyProperty for the CanGoForward property. /// Flags: None /// Default Value: false /// Readonly: true /// public static readonly DependencyProperty CanGoForwardProperty = JournalNavigationScope.CanGoForwardProperty.AddOwner(typeof(Frame)); ////// List of back journal entries. Available only when the frame owns its own journal. /// public static readonly DependencyProperty BackStackProperty = JournalNavigationScope.BackStackProperty.AddOwner(typeof(Frame)); ////// List of back journal entries. Available only when the frame owns its own journal. /// public static readonly DependencyProperty ForwardStackProperty = JournalNavigationScope.ForwardStackProperty.AddOwner(typeof(Frame)); ////// public static readonly DependencyProperty NavigationUIVisibilityProperty = DependencyProperty.Register( "NavigationUIVisibility", typeof(NavigationUIVisibility), typeof(Frame), new PropertyMetadata(NavigationUIVisibility.Automatic)); ////// public NavigationUIVisibility NavigationUIVisibility { get { return (NavigationUIVisibility)GetValue(NavigationUIVisibilityProperty); } set { SetValue(NavigationUIVisibilityProperty, value); } } ////// DependencyProperty for SandboxExternalContent property. /// public static readonly DependencyProperty SandboxExternalContentProperty = DependencyProperty.Register( "SandboxExternalContent", typeof(bool), typeof(Frame), new FrameworkPropertyMetadata(BooleanBoxes.FalseBox, new PropertyChangedCallback(OnSandboxExternalContentPropertyChanged), new CoerceValueCallback(CoerceSandBoxExternalContentValue))); ////// If set to true, the navigated content is isolated. /// public bool SandboxExternalContent { get { return (bool) GetValue(SandboxExternalContentProperty); } set { // This feature is disabled in partial trust due to a P3P violation bool fSandBox = (bool)value; SecurityHelper.ThrowExceptionIfSettingTrueInPartialTrust(ref fSandBox); SetValue(SandboxExternalContentProperty, fSandBox); } } ////// Called when SandboxExternalContentProperty is invalidated on 'd'. If the value becomes /// true, then the frame is refreshed to sandbox any content. /// private static void OnSandboxExternalContentPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { Frame frame = (Frame)d; // we do not want an individual to be able to set this property to true // in partial trust // This feature is disabled in partial trust due to a P3P violation bool fSandBox = (bool)e.NewValue; SecurityHelper.ThrowExceptionIfSettingTrueInPartialTrust(ref fSandBox); if (fSandBox && !(bool)e.OldValue) { frame.NavigationService.Refresh(); } } private static object CoerceSandBoxExternalContentValue(DependencyObject d, object value) { // we do not want an individual to be able to set this property to true // in partial trust // This feature is disabled in partial trust due to a P3P violation bool fSandBox = (bool)value; SecurityHelper.ThrowExceptionIfSettingTrueInPartialTrust(ref fSandBox); return fSandBox; } // // JournalOwnership ////// DependencyProperty for the JournalOwnership property /// public static readonly DependencyProperty JournalOwnershipProperty = DependencyProperty.Register( "JournalOwnership", typeof(JournalOwnership), typeof(Frame), new FrameworkPropertyMetadata( JournalOwnership.Automatic, new PropertyChangedCallback(OnJournalOwnershipPropertyChanged), new CoerceValueCallback(CoerceJournalOwnership)), new ValidateValueCallback(ValidateJournalOwnershipValue)); private static bool ValidateJournalOwnershipValue(object value) { JournalOwnership jo = (JournalOwnership)value; return jo == JournalOwnership.Automatic || jo == JournalOwnership.UsesParentJournal || jo == JournalOwnership.OwnsJournal; } private static void OnJournalOwnershipPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((Frame)d).OnJournalOwnershipPropertyChanged((JournalOwnership)e.NewValue); } private void OnJournalOwnershipPropertyChanged(JournalOwnership newValue) { // NavigationService.InvalidateJournalNavigationScope() will be called (recursively) // when making an ownership change and will throw if there is a navigation in progress. switch (_journalOwnership/*previous value*/) { case JournalOwnership.Automatic: switch (newValue) { case JournalOwnership.OwnsJournal: SwitchToOwnJournal(); break; case JournalOwnership.UsesParentJournal: SwitchToParentJournal(); break; } break; case JournalOwnership.OwnsJournal: Debug.Assert(_ownJournalScope != null); switch (newValue) { case JournalOwnership.Automatic: Debug.Fail("UsesOwnJournal->Automatic transition should be blocked by CoerceJournalOwnership()."); break; case JournalOwnership.UsesParentJournal: SwitchToParentJournal(); break; } break; case JournalOwnership.UsesParentJournal: Debug.Assert(_ownJournalScope == null); switch (newValue) { case JournalOwnership.Automatic: // The effective journal ownership is not going to change unless the // frame is reparented (or, more unlikely, the parent's journal becomes // unavailable). This invalidation is done only so that the next // navigation causes a switch to UsesParentJournal, to be consistent // with the initial transition from Automatic. _navigationService.InvalidateJournalNavigationScope(); break; case JournalOwnership.OwnsJournal: SwitchToOwnJournal(); break; } break; } _journalOwnership = newValue; } private static object CoerceJournalOwnership(DependencyObject d, object newValue) { JournalOwnership prevValue = ((Frame)d)._journalOwnership; // Switching from OwnsJournal to Automatic is not defined to have any useful effect. // (Even if reparented, Frame will not relinquish its own journal to start using its new // parent's one.) But in order to be able to maintain some stronger invariants, this transition // is blocked here. if (prevValue == JournalOwnership.OwnsJournal && (JournalOwnership)newValue == JournalOwnership.Automatic) { return JournalOwnership.OwnsJournal; } return newValue; } ////// Journal ownership setting for this frame /// public JournalOwnership JournalOwnership { get { Debug.Assert(_journalOwnership == (JournalOwnership)GetValue(JournalOwnershipProperty)); return _journalOwnership; } set { if (value != _journalOwnership) { SetValue(JournalOwnershipProperty, value); } } } ////// Frame's associated NavigationService. /// public NavigationService NavigationService { get { VerifyAccess(); return _navigationService; } } #endregion //----------------------------------------------------- // // Protected Methods // //----------------------------------------------------- #region Protected Methods ////// Creates AutomationPeer ( protected override AutomationPeer OnCreateAutomationPeer() { return new FrameAutomationPeer(this); } ///) /// /// Add an object child to this control /// protected override void AddChild(object value) { throw new InvalidOperationException(SR.Get(SRID.FrameNoAddChild)); } ////// Add a text string to this control /// protected override void AddText(string text) { XamlSerializerUtil.ThrowIfNonWhiteSpaceInAddText(text, this); } #endregion #region Event Handlers private void _OnBPReady(Object o, BPReadyEventArgs e) { // update content property Content = e.Content; // Need to refresh everytime the child changed InvalidateMeasure(); // We post a dispatcher work item to fire ContentRendered // only if this is Loaded in the tree. If not, we will // post it from the LoadedHandler. This guarantees that // we don't fire ContentRendered on a subtree that is not // connected to a PresentationSource if (IsLoaded == true) { PostContentRendered(); } else { // _postContentRenderedFromLoadedHandler == true means // that we deferred to the Loaded event to PostConetentRendered // for the previous content change and Loaded has not fired yet. // Thus we don't want to hook up another event handler if (_postContentRenderedFromLoadedHandler == false) { this.Loaded += new RoutedEventHandler(LoadedHandler); _postContentRenderedFromLoadedHandler = true; } } } private void LoadedHandler(object sender, RoutedEventArgs args) { if (_postContentRenderedFromLoadedHandler == true) { PostContentRendered(); _postContentRenderedFromLoadedHandler = false; this.Loaded -= new RoutedEventHandler(LoadedHandler); } } ///Keep this method in sync with Window.PostContentRendered(). private void PostContentRendered() { // Post the firing of ContentRendered as Input priority work item so // that ContentRendered will be fired after render query empties. if (_contentRenderedCallback != null) { // Content was changed again before the previous rendering completed (or at least // before the Dispatcher got to Input priority callbacks). _contentRenderedCallback.Abort(); } _contentRenderedCallback = Dispatcher.BeginInvoke(DispatcherPriority.Input, (DispatcherOperationCallback) delegate (object unused) { _contentRenderedCallback = null; OnContentRendered(EventArgs.Empty); return null; }, this); } private void OnQueryGoBack(object sender, CanExecuteRoutedEventArgs e) { Debug.Assert(sender == this && _ownJournalScope != null); e.CanExecute = _ownJournalScope.CanGoBack; e.Handled = true; } private void OnGoBack(object sender, ExecutedRoutedEventArgs e) { Debug.Assert(sender == this && _ownJournalScope != null); _ownJournalScope.GoBack(); e.Handled = true; } private void OnQueryGoForward(object sender, CanExecuteRoutedEventArgs e) { Debug.Assert(sender == this && _ownJournalScope != null); e.CanExecute = _ownJournalScope.CanGoForward; e.Handled = true; } private void OnGoForward(object sender, ExecutedRoutedEventArgs e) { Debug.Assert(sender == this && _ownJournalScope != null); _ownJournalScope.GoForward(); e.Handled = true; } private void OnNavigateJournal(object sender, ExecutedRoutedEventArgs e) { Debug.Assert(sender == this && _ownJournalScope != null); // The following checks are needed because anyone could send the NavigateJournal command. FrameworkElement journalEntryUIElem = e.Parameter as FrameworkElement; if (journalEntryUIElem != null) { JournalEntry je = journalEntryUIElem.DataContext as JournalEntry; if (je != null) { if (_ownJournalScope.NavigateToEntry(je)) { e.Handled = true; } } } } private void OnQueryRefresh(object sender, CanExecuteRoutedEventArgs e) { Debug.Assert(sender == this && _ownJournalScope != null); e.CanExecute = Content != null; } private void OnRefresh(object sender, ExecutedRoutedEventArgs e) { Debug.Assert(sender == this && _ownJournalScope != null); _navigationService.Refresh(); e.Handled = true; } private void OnBrowseStop(object sender, ExecutedRoutedEventArgs e) { Debug.Assert(sender == this && _ownJournalScope != null); _ownJournalScope.StopLoading(); e.Handled = true; } #endregion #region Event Management ////// When a Frame-content's event bubbling up Visual tree, we need to adjust /// the source of the event to the frame itself. /// /// /// Routed Event Args /// ////// Returns new source. (Current Frame object) /// internal override object AdjustEventSource(RoutedEventArgs e) { e.Source=this; return this; } #endregion #region Overiding ContentControl implementation ////// Return text representing this Frame /// internal override string GetPlainText() { if (this.Source != null) { return Source.ToString(); } else { return String.Empty; } } ////// This method is used by TypeDescriptor to determine if this property should /// be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] public override bool ShouldSerializeContent() { // When uri of NavigationService is valid and can be used to // relaod, we do not serialize content Invariant.Assert(_navigationService != null, "_navigationService should never be null here"); return ( !_navigationService.CanReloadFromUri && Content != null); } #endregion Overding ContentControl implementation #region NavigationService support private static void OnParentNavigationServiceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { Debug.Assert(d as Frame != null && ((Frame)d).NavigationService != null); ((Frame) d).NavigationService.OnParentNavigationServiceChanged(); } ////// Called when the template's visual tree is created. /// public override void OnApplyTemplate() { base.OnApplyTemplate(); // Get the root element of the style Visual v = TemplateChild; if (v != null) { NavigationService.VisualTreeAvailable(v); } } #region INavigatorImpl members // Note: OnSourceUpdatedFromNavService is next to the other Source-related members of Frame. Visual INavigatorImpl.FindRootViewer() { return NavigationHelper.FindRootViewer(this, "PART_FrameCP"); } #endregion INavigatorImpl #endregion NavigationService support #region INavigator implementation JournalNavigationScope INavigator.GetJournal(bool create) { return GetJournal(create); } ////// private JournalNavigationScope GetJournal(bool create) { Invariant.Assert(_ownJournalScope != null ^ _journalOwnership != JournalOwnership.OwnsJournal); if (_ownJournalScope != null) return _ownJournalScope; JournalNavigationScope jns = GetParentJournal(create); if (jns != null) { JournalOwnership = JournalOwnership.UsesParentJournal; return jns; } if (create && _journalOwnership == JournalOwnership.Automatic) { JournalOwnership = JournalOwnership.OwnsJournal; } return _ownJournalScope; } ////// /// True when the frame has its own journal and there is a navigable entry in the forward stack. /// If the frame doesn't own a journal, its parent or corresponding NavigationService may be /// able to navigate it forward. /// public bool CanGoForward { get { bool canGoFwd = _ownJournalScope != null && _ownJournalScope.CanGoForward; Debug.Assert(canGoFwd == (bool)GetValue(CanGoForwardProperty)); return canGoFwd; } } ////// True when the frame has its own journal and there is a navigable entry in the back stack. /// If the frame doesn't own a journal, its parent or corresponding NavigationService may be /// able to navigate it back. /// public bool CanGoBack { get { bool canGoBack = _ownJournalScope != null && _ownJournalScope.CanGoBack; Debug.Assert(canGoBack == (bool)GetValue(CanGoBackProperty)); return canGoBack; } } ////// Adds a new journal entry to NavigationWindow's back history. /// /// The custom content state (or view state) to be encapsulated in the /// journal entry. If null, IProvideCustomContentState.GetContentState() will be called on /// the NavigationWindow.Content or Frame.Content object. /// public void AddBackEntry(CustomContentState state) { VerifyAccess(); _navigationService.AddBackEntry(state); } ////// Removes the first JournalEntry from the frame's back stack. /// ///The frame doesn't own a journal. public JournalEntry RemoveBackEntry() { if (_ownJournalScope == null) throw new InvalidOperationException(SR.Get(SRID.InvalidOperation_NoJournal)); return _ownJournalScope.RemoveBackEntry(); } ////// Navigates to the Uri and downloads the content. Whether the navigation is /// performed synchronously or asynchronously depends on the current default navigation behavior. /// /// URI of the application or content being navigated to. ///bool indicating whether the navigation was successfully started or not public bool Navigate(Uri source) { VerifyAccess(); return _navigationService.Navigate(source); } // // INavigator.Navigate // ////// This method navigates this Frame to the given Uri. /// /// The URI to be navigated to. /// enables the develeoper to supply an extra object, that will be returned in the NavigationEventArgs of the Navigated event. The extra data enables the developer /// to identify the source of the navigation, in the presence of /// multiple navigations. /// ///bool indicating whether the navigation was successfully started or not public bool Navigate(Uri source, Object extraData) { VerifyAccess(); return _navigationService.Navigate(source, extraData); } ////// Navigates synchronously to an existing element tree. /// /// Root of the element tree being navigated to. ///bool indicating whether the navigation was successfully started or not public bool Navigate(Object content) { VerifyAccess(); return _navigationService.Navigate(content); } // // INavigator.Navigate(object) // ////// This method synchronously navigates this Frame to the /// given Element. /// /// The Element to be navigated to. /// enables the develeoper to supply an extra object, that will be returned in the NavigationEventArgs of the Navigated event. The extra data enables the developer /// to identify the source of the navigation, in the presence of /// multiple navigations. /// ///bool indicating whether the navigation was successfully started or not public bool Navigate(Object content, Object extraData) { VerifyAccess(); return _navigationService.Navigate(content, extraData); } ////// Navigates the frame to the next journal entry. The operation is available only when /// the frame has its own journal. If not, try navigating the parent or the corresponding /// NavigationService. /// ///The frame doesn't own a journal. ///There is no forward journal entry to go to. public void GoForward() { if (_ownJournalScope == null) throw new InvalidOperationException(SR.Get(SRID.InvalidOperation_NoJournal)); _ownJournalScope.GoForward(); } ////// Navigates the frame to the previous journal entry. The operation is available only when /// the frame has its own journal. If not, try navigating the parent or the corresponding /// NavigationService. /// ///The frame doesn't own a journal. ///There is no back journal entry to go to. public void GoBack() { if(_ownJournalScope == null) throw new InvalidOperationException(SR.Get(SRID.InvalidOperation_NoJournal)); _ownJournalScope.GoBack(); } ////// StopLoading aborts asynchronous navigations that haven't been processed yet or that are /// still being downloaded. SopLoading does not abort parsing of the downloaded streams. /// The NavigationStopped event is fired only if the navigation was aborted. /// public void StopLoading() { VerifyAccess(); _navigationService.StopLoading(); } ////// Reloads the current content. /// public void Refresh() { VerifyAccess(); _navigationService.Refresh(); } ////// Uri for the current page. Getting this property always /// returns the URI of the content thats currently displayed. /// regardless of whether a navigation is in progress or not. /// ///public Uri CurrentSource { get { return _navigationService.CurrentSource; } } /// /// List of back journal entries. Available only when the frame has its own journal. /// public IEnumerable BackStack { get { IEnumerable backStack = _ownJournalScope == null ? null : _ownJournalScope.BackStack; Debug.Assert(backStack == GetValue(BackStackProperty)); return backStack; } } ////// List of forward journal entries. Available only when the frame has its own journal. /// public IEnumerable ForwardStack { get { IEnumerable fwdStack = _ownJournalScope == null ? null : _ownJournalScope.ForwardStack; Debug.Assert(fwdStack == GetValue(ForwardStackProperty)); return fwdStack; } } ////// Raised just before a navigation takes place. This event is fired for frame /// navigations as well as top-level page navigations, so may fire multiple times /// during the download of a page. /// The NavigatingCancelEventArgs contain the uri or root element of the content /// being navigated to and an enum value that indicates the type of navigation. /// Canceling this event prevents the application from navigating. /// Note: An application hosted in the browser cannot prevent navigation away from /// the application by canceling this event. /// Note: In the PDC build, if an application hosts the WebOC, this event is not raised /// for navigations within the WebOC. /// public event NavigatingCancelEventHandler Navigating { add { _navigationService.Navigating += value; } remove { _navigationService.Navigating -= value; } } ////// Raised at periodic intervals while a navigation is taking place. /// The NavigationProgressEventArgs tell how many total bytes need to be downloaded and /// how many have been sent at the moment the event is fired. This event can be used to provide /// a progress indicator to the user. /// public event NavigationProgressEventHandler NavigationProgress { add { _navigationService.NavigationProgress += value; } remove { _navigationService.NavigationProgress -= value; } } ////// Raised an error is encountered during a navigation. /// The NavigationFailedEventArgs contains /// the exception that was thrown. By default Handled property is set to false, /// which allows the exception to be rethrown. /// The event handler can prevent exception from throwing /// to the user by setting the Handled property to true /// public event NavigationFailedEventHandler NavigationFailed { add { _navigationService.NavigationFailed += value; } remove { _navigationService.NavigationFailed -= value; } } ////// Raised after navigation the target has been found and the download has begun. This event /// is fired for frame navigations as well as top-level page navigations, so may fire /// multiple times during the download of a page. /// For an asynchronous navigation, this event indicates that a partial element tree /// has been handed to the parser, but more bits are still coming. /// For a synchronous navigation, this event indicates the entire tree has been /// handed to the parser. /// The NavigationEventArgs contain the uri or root element of the content being navigated to. /// This event is informational only, and cannot be canceled. /// public event NavigatedEventHandler Navigated { add { _navigationService.Navigated += value; } remove { _navigationService.Navigated -= value; } } // // INavigator.LoadCompleted // ////// Raised after the entire page, including all images and frames, has been downloaded /// and parsed. This is the event to handle to stop spinning the globe. The developer /// should check the IsNavigationInitiator property on the NavigationEventArgs to determine /// whether to stop spinning the globe. /// The NavigationEventArgs contain the uri or root element of the content being navigated to, /// and a IsNavigationInitiator property that indicates whether this is a new navigation /// initiated by this Frame, or whether this navigation is being propagated down /// from a higher level navigation taking place in a containing window or frame. /// This event is informational only, and cannot be canceled. /// public event LoadCompletedEventHandler LoadCompleted { add { _navigationService.LoadCompleted += value; } remove { _navigationService.LoadCompleted -= value; } } ////// Raised when a navigation or download has been interrupted because the user clicked /// the Stop button, or the Stop method was invoked. /// The NavigationEventArgs contain the uri or root element of the content being navigated to. /// This event is informational only, and cannot be canceled. /// public event NavigationStoppedEventHandler NavigationStopped { add { _navigationService.NavigationStopped += value; } remove { _navigationService.NavigationStopped -= value; } } ////// Raised when a navigation uri contains a fragment. This event is fired before the element is scrolled /// into view and allows the listener to respond to the fragment in a custom way. /// public event FragmentNavigationEventHandler FragmentNavigation { add { _navigationService.FragmentNavigation += value; } remove { _navigationService.FragmentNavigation -= value; } } #endregion INavigator implementation #region IJournalNavigationScopeHost Members void IJournalNavigationScopeHost.VerifyContextAndObjectState() { VerifyAccess(); } void IJournalNavigationScopeHost.OnJournalAvailable() { // BackStackProperty & ForwardStackProperty should be set by JournalNavigationScope. Debug.Assert(GetValue(BackStackProperty) == _ownJournalScope.BackStack); } bool IJournalNavigationScopeHost.GoBackOverride() { return false; // not overriding here } bool IJournalNavigationScopeHost.GoForwardOverride() { return false; } #endregion #region IJournalState Members ////// When Frame's parent container navigates away and if its content is not keep-alive, /// the frame's current page needs to be remembered. In addition, if the frame has its own /// journal, it has to be preserved too. Class FramePersistState captures this "metajournaling" /// state. It will become part of the journal entry created for the navigation in the parent /// container (stored within a DataStreams instance). /// [Serializable] private class FramePersistState : CustomJournalStateInternal { internal JournalEntry JournalEntry; internal Guid NavSvcGuid; internal JournalOwnership JournalOwnership; internal Journal Journal; internal override void PrepareForSerialization() { if (JournalEntry != null) { if (JournalEntry.IsAlive()) // not serializable { JournalEntry = null; // Only the NavigationService GUID will be restored. // See related case and explanation in Frame.GetJournalState(). } else { Debug.Assert(JournalEntry.GetType().IsSerializable); } } if (Journal != null) { Journal.PruneKeepAliveEntries(); } } }; CustomJournalStateInternal IJournalState.GetJournalState(JournalReason journalReason) { if (journalReason != JournalReason.NewContentNavigation) { return null; } FramePersistState state = new FramePersistState(); // Save a JournalEntry for the current content. state.JournalEntry = _navigationService.MakeJournalEntry(JournalReason.NewContentNavigation); // The current Content may be null or may not want to be journaled (=> JournalEntry=null). // But we still need to save and then restore the NS GUID - there may be other JEs keyed // by this GUID value. // i. There is a somewhat similar case in ApplicationProxyInternal._GetSaveHistoryBytesDelegate(). state.NavSvcGuid = _navigationService.GuidId; state.JournalOwnership = _journalOwnership; if (_ownJournalScope != null) { Debug.Assert(_journalOwnership == JournalOwnership.OwnsJournal); // No need to make a copy here because this Frame object will be discarded. // (Supposedly the parent container is navigating away.) state.Journal = _ownJournalScope.Journal; } return state; } void IJournalState.RestoreJournalState(CustomJournalStateInternal cjs) { FramePersistState state = (FramePersistState)cjs; _navigationService.GuidId = state.NavSvcGuid; // Because the JournalOwnershipProperty doesn't have the FrameworkPropertyMetadataOptions.Journal // flag, the parser will always set the value specified in markup, which may be different from // state.JournalOwnership. So, at this point JournalOwnership is not necessarily Automatic // (the default). JournalOwnership = state.JournalOwnership; if(_journalOwnership == JournalOwnership.OwnsJournal) { Invariant.Assert(state.Journal != null); _ownJournalScope.Journal = state.Journal; } if(state.JournalEntry != null) { state.JournalEntry.Navigate(this, NavigationMode.Back); } } #endregion IJournalState //------------------------------------------------------ // // Internal Methods // //----------------------------------------------------- #region Internal Methods internal override void OnPreApplyTemplate() { base.OnPreApplyTemplate(); if (_ownJournalScope != null) { // This causes the Journal instance to be created. BackStackProperty and ForwardStackProperty // should be set before the navigation chrome data-binds to them but after any Journal is // restored from FramePersistState. _ownJournalScope.EnsureJournal(); } } // Invalidate resources on the frame content if the content isn't // reachable via the visual/logical tree internal override void OnThemeChanged() { // If the frame does not have a template generated tree then its // content is not reachable via a tree walk. DependencyObject d; if (!HasTemplateGeneratedSubTree && (d = Content as DependencyObject) != null) { FrameworkElement fe; FrameworkContentElement fce; Helper.DowncastToFEorFCE(d, out fe, out fce, false); if (fe != null || fce != null) { TreeWalkHelper.InvalidateOnResourcesChange(fe, fce, ResourcesChangeInfo.ThemeChangeInfo); } } } #endregion Internal Methods //------------------------------------------------------ // // Private Methods // //------------------------------------------------------ #region Private Methods private JournalNavigationScope GetParentJournal(bool create) { JournalNavigationScope jns = null; NavigationService parentNS = _navigationService.ParentNavigationService; if (parentNS != null) { jns = parentNS.INavigatorHost.GetJournal(create); } return jns; } ///Does not update the JournalOwnershipProperty. private void SwitchToOwnJournal() { Debug.Assert(_ownJournalScope == null ^ _journalOwnership == JournalOwnership.OwnsJournal); if (_ownJournalScope == null) { // Entries created for this frame in the parent's journal have to be removed. JournalNavigationScope parentJns = GetParentJournal(false/*don't create*/); if (parentJns != null) { parentJns.Journal.RemoveEntries(_navigationService.GuidId); } _ownJournalScope = new JournalNavigationScope(this); _navigationService.InvalidateJournalNavigationScope(); // BackStackProperty & ForwardStackProperty should become available immediately if // OwnsJournal is set *after* Frame is already loaded. // See comment in OnPreApplyTemplate(). if (IsLoaded) { _ownJournalScope.EnsureJournal(); } AddCommandBinding(new CommandBinding(NavigationCommands.BrowseBack, OnGoBack, OnQueryGoBack)); AddCommandBinding(new CommandBinding(NavigationCommands.BrowseForward, OnGoForward, OnQueryGoForward)); AddCommandBinding(new CommandBinding(NavigationCommands.NavigateJournal, OnNavigateJournal)); AddCommandBinding(new CommandBinding(NavigationCommands.Refresh, OnRefresh, OnQueryRefresh)); AddCommandBinding(new CommandBinding(NavigationCommands.BrowseStop, OnBrowseStop)); } _journalOwnership = JournalOwnership.OwnsJournal; } ///Does not update the JournalOwnershipProperty. private void SwitchToParentJournal() { Debug.Assert(_ownJournalScope == null ^ _journalOwnership == JournalOwnership.OwnsJournal); if (_ownJournalScope != null) { _ownJournalScope = null; _navigationService.InvalidateJournalNavigationScope(); JournalNavigationScope.ClearDPValues(this); foreach (CommandBinding cb in _commandBindings) { base.CommandBindings.Remove(cb); } _commandBindings = null; } _journalOwnership = JournalOwnership.UsesParentJournal; } private void AddCommandBinding(CommandBinding b) { base.CommandBindings.Add(b); // Store the CommandBinding reference so that it can be removed in case the frame loses // its JournalNavigationScope. if (_commandBindings == null) { _commandBindings = new List(6); } _commandBindings.Add(b); } #endregion Private Methods //----------------------------------------------------- // // Private Fields // //------------------------------------------------------ #region Private Fields private bool _postContentRenderedFromLoadedHandler = false; private DispatcherOperation _contentRenderedCallback; private NavigationService _navigationService; private bool _sourceUpdatedFromNavService; /// All changes should be made via the JournalOwnership property setter. private JournalOwnership _journalOwnership = JournalOwnership.Automatic; private JournalNavigationScope _ownJournalScope; private List_commandBindings; #endregion Private Fields #region DTypeThemeStyleKey // Returns the DependencyObjectType for the registered ThemeStyleKey's default // value. Controls will override this method to return approriate types. internal override DependencyObjectType DTypeThemeStyleKey { get { return _dType; } } private static DependencyObjectType _dType; #endregion DTypeThemeStyleKey } } // 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
- ColorConverter.cs
- FileVersion.cs
- CharacterBuffer.cs
- CmsUtils.cs
- TableStyle.cs
- DrawingDrawingContext.cs
- SignedPkcs7.cs
- xdrvalidator.cs
- Transform3D.cs
- Block.cs
- BindableTemplateBuilder.cs
- CodeTypeOfExpression.cs
- WindowsClientCredential.cs
- WsiProfilesElementCollection.cs
- RotateTransform3D.cs
- TimeManager.cs
- InstanceContextManager.cs
- ClrPerspective.cs
- RecordsAffectedEventArgs.cs
- HttpRequestMessageProperty.cs
- Evidence.cs
- WasAdminWrapper.cs
- XPathAncestorIterator.cs
- DBSchemaTable.cs
- ProtocolElementCollection.cs
- BatchStream.cs
- UpdatePanelTrigger.cs
- ConsumerConnectionPoint.cs
- TransportSecurityProtocolFactory.cs
- ADConnectionHelper.cs
- QilGeneratorEnv.cs
- PassportIdentity.cs
- PostBackTrigger.cs
- EntityCommandExecutionException.cs
- PropertyMapper.cs
- EmptyCollection.cs
- Byte.cs
- ActiveXHelper.cs
- BitmapEffectvisualstate.cs
- DeclaredTypeValidatorAttribute.cs
- SoapProcessingBehavior.cs
- SqlPersonalizationProvider.cs
- VirtualizedCellInfoCollection.cs
- NativeMethods.cs
- SQLDateTime.cs
- WebContext.cs
- AssemblyCache.cs
- SkipStoryboardToFill.cs
- CollectionViewSource.cs
- PointCollectionValueSerializer.cs
- AsymmetricSignatureDeformatter.cs
- CombinedGeometry.cs
- Table.cs
- DataGridViewColumnCollection.cs
- UrlParameterWriter.cs
- ErrorTolerantObjectWriter.cs
- ExtensibleClassFactory.cs
- _OverlappedAsyncResult.cs
- InvalidComObjectException.cs
- SessionStateContainer.cs
- Stylus.cs
- PageSettings.cs
- ArrayConverter.cs
- StrokeFIndices.cs
- RemotingConfigParser.cs
- SystemUnicastIPAddressInformation.cs
- TransportOutputChannel.cs
- ExtensibleClassFactory.cs
- CapabilitiesSection.cs
- InstanceOwnerException.cs
- ProfileService.cs
- GeometryDrawing.cs
- XPathNode.cs
- DataObjectFieldAttribute.cs
- ContextMenuStrip.cs
- TreeView.cs
- WebPartVerb.cs
- MemberMemberBinding.cs
- ImageBrush.cs
- Baml2006Reader.cs
- HebrewNumber.cs
- ModifiableIteratorCollection.cs
- IgnoreSection.cs
- SchemaNotation.cs
- BooleanProjectedSlot.cs
- HtmlGenericControl.cs
- XmlDigitalSignatureProcessor.cs
- RepeatEnumerable.cs
- DnsPermission.cs
- QueuePathDialog.cs
- BinarySecretKeyIdentifierClause.cs
- AttachmentCollection.cs
- SecureStringHasher.cs
- AsymmetricCryptoHandle.cs
- QuaternionConverter.cs
- BuildProviderCollection.cs
- BackEase.cs
- LinkUtilities.cs
- PointCollection.cs
- TripleDES.cs