Frame.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / 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: ChangoV       "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 [....] 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.
//---------------------------------------------------------------------------- 
//
// 
//    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: ChangoV       "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 [....] 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

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK