JournalEntry.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / System / Windows / Navigation / JournalEntry.cs / 1 / JournalEntry.cs

                            //---------------------------------------------------------------------------- 
//
// File: JournalEntry.cs
//
// Description: 
// implements the Avalon Journal Entry Object
// 
// 
// History:
//  7/30/2001:  t-ypchen        Created 
//  5/19/2003:  [....]         Ported to WCP tree
//  2/12/2004:  [....]            Major refactoring-split JournalEntry into subclasses
//  7/25/2005:  [....]         Added CustomContentState journaling
//  9/02/2005:  [....]         Introduced JournalEntryGroupState; overall refactoring and PageFunction fixes 
//  1/20/2006:  [....]         Moved all internal classes to MS.Internal.AppModel
// 
// Copyright (C) 2003 by Microsoft Corporation.  All rights reserved. 
//
//--------------------------------------------------------------------------- 

using System;
using System.Collections;
using System.Diagnostics; 
using System.IO;
using System.IO.Packaging; 
using System.Globalization; 
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary; 
using System.Security.Permissions;
using System.Security ;
using System.Windows.Markup;
using System.Xml; 

using MS.Internal.AppModel; 
using MS.Internal; 
using MS.Internal.Utility;
 
using System.Windows.Controls.Primitives;

//In order to avoid generating warnings about unknown message numbers and
//unknown pragmas when compiling your C# source code with the actual C# compiler, 
//you need to disable warnings 1634 and 1691. (Presharp Documentation)
#pragma warning disable 1634, 1691 
 
namespace System.Windows.Navigation
{ 
    /// 
    /// Derived classes encapsulate content/view state associated with custom journal entries.
    /// Object instances are passed to AddBackEntry() and also requested by the framework via the
    /// IProvideCustomContentState interface. 
    /// 
    [Serializable] 
    public abstract class CustomContentState 
    {
        ///  
        /// Provides the display name for the journal entry created for this custom content state.
        /// If the returned string is null or empty, the name will be obtained, in order of
        /// precedence, from either: the JournalEntry.Name or Page.Title attached property set on
        /// the content root; the Window's title; or the current source URI. 
        /// 
        public virtual string JournalEntryName 
        { 
            get { return null; }
        } 

        /// 
        /// Called by the framework when navigation to a custom journal entry occurs. The method
        /// re-applies the encapsulated content/view state to the base content (element tree). 
        /// 
        public abstract void Replay(NavigationService navigationService, NavigationMode mode); 
    }; 

    ///  
    /// Interface to be implemented by a navigator's Content object (root element). Provides
    /// snapshots of the content state for custom journal entries.
    /// 
    ///  As an alternative to implementing this interface, an application can handle 
    /// the Navigating event and set the NavigatingCancelEventArgs.ContentStateToSave property.
    /// However, this method does not preserve the state of child frames. 
    ///  
    public interface IProvideCustomContentState
    { 
        /// 
        /// Override this method to capture the custom content state or the content's view state.
        /// 
        ///  
        CustomContentState GetContentState();
    }; 
 
    /// 
    /// The base class for all journal entries. 
    /// 
    /// 
    /// Custom serialization implementation is needed (ISerializable) because the DependencyObject base
    /// is not [Serializable]. The Name DP is saved explicitly. (Even though it is registered as 
    /// attached, it is also set on JE. KeepAlive is not saved, because KA entries are pruned before
    /// TravelLog serialization.) 
    ///  
    [Serializable]
    public class JournalEntry : DependencyObject, ISerializable 
    {
        // Ctors
        /////////////////////////////////////////////////////////////////////
 
        #region Ctors
 
        internal JournalEntry(JournalEntryGroupState jeGroupState, Uri uri) 
        {
            _jeGroupState = jeGroupState; 
            if (jeGroupState != null)
            {
                // Seems convenient to always do this here.
                jeGroupState.GroupExitEntry = this; 
            }
            Source = uri; 
        } 

        ///  
        /// Serialization constructor. Marked Protected so derived classes can be deserialized correctly
        /// 
        protected JournalEntry(SerializationInfo info, StreamingContext context)
        { 
            _id = info.GetInt32("_id");
            _source = (Uri)info.GetValue("_source", typeof(Uri)); 
            _entryType = (JournalEntryType)info.GetValue("_entryType", typeof(JournalEntryType)); 
            _jeGroupState = (JournalEntryGroupState)info.GetValue("_jeGroupState", typeof(JournalEntryGroupState));
            _customContentState = (CustomContentState)info.GetValue("_customContentState", typeof(CustomContentState)); 
            _rootViewerState = (CustomJournalStateInternal)info.GetValue("_rootViewerState", typeof(CustomJournalStateInternal));
            this.Name = info.GetString("Name");
        }
 
        /// 
        /// ISerializable implementation 
        ///  
        /// 
        /// Critical: does object serialization 
        /// Public OK: has a LinkDemand
        /// 
        [SecurityCritical]
        [SecurityPermissionAttribute(SecurityAction.LinkDemand, SerializationFormatter = true)] 
        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
        { 
            if (info == null) 
            {
                throw new ArgumentNullException("info"); 
            }

            info.AddValue("_id", _id);
            info.AddValue("_source", _source); 
            info.AddValue("_entryType", _entryType);
            // All these have to be written even if they are null. Othewise info.GetValue() would throw 
            // in the serialization ctor. 
            info.AddValue("_jeGroupState", _jeGroupState);
            info.AddValue("_customContentState", _customContentState); 
            info.AddValue("_rootViewerState", _rootViewerState);
            info.AddValue("Name", this.Name); // see Remarks on class declaration
        }
        #endregion 

        // Public methods 
        ///////////////////////////////////////////////////////////////////// 

        #region Public Methods 

        /// 
        /// Reads the attached property JournalEntry.Name from the given element.
        /// Setting it at the root element of a navigator will update NavWin�s dropdown menu when navigating inside of that navigator. 
        /// 
        /// The element from which to read the attached property. 
        /// The property's value. 
        /// 
        public static string GetName(DependencyObject dependencyObject) 
        {
            // not verifying Context on static method

            return dependencyObject != null ? (string)dependencyObject.GetValue(NameProperty) : null; 
        }
 
        ///  
        /// Writes the attached property JournalEntry.Name to the given element.
        ///  
        /// The element to which to write the attached property.
        /// The property value to set
        /// 
        public static void SetName(DependencyObject dependencyObject, string name) 
        {
            // not verifying Context on static method 
 
            if (dependencyObject == null)
            { 
                throw new ArgumentNullException("dependencyObject");
            }

            dependencyObject.SetValue(NameProperty, name); 
        }
 
        ///  
        /// Reads the attached property KeepAlive from the given element. This is not a property of the
        /// journal, but rather a flag to indicate that this tree should be keep alived 
        /// as part of journaling. If KeepAlive == true, then the entire tree will be saved.
        /// 
        /// The element from which to read the attached property.
        /// The property's value. 
        /// 
        public static bool GetKeepAlive(DependencyObject dependencyObject) 
        { 
            // not verifying Context on static method
            if (dependencyObject == null) 
            {
                throw new ArgumentNullException("dependencyObject");
            }
 
            return (bool)dependencyObject.GetValue(KeepAliveProperty);
        } 
 
        /// 
        /// Writes the attached property KeepAlive to the given element. See above. 
        /// 
        /// The element to which to write the attached property.
        /// The property value to set
        ///  
        public static void SetKeepAlive(DependencyObject dependencyObject, bool keepAlive)
        { 
            // not verifying Context on static method 

            if (dependencyObject == null) 
            {
                throw new ArgumentNullException("dependencyObject");
            }
 
            dependencyObject.SetValue(KeepAliveProperty, keepAlive);
        } 
        #endregion 

        // Public properties 
        /////////////////////////////////////////////////////////////////////

        #region Public Properties
        ///  
        /// The Uri of the stored Page
        ///  
        public Uri Source 
        {
            get { return _source; } 
            set { _source = BindUriHelper.GetUriRelativeToPackAppBase(value); }
        }

        ///  The custom content state or content view state associated with the entry  
        public CustomContentState CustomContentState
        { 
            get { return _customContentState; } 
            internal set { _customContentState = value; }
        } 

        /// 
        /// The name of the journal entry to be displayed in the drop-down list
        /// on the Back/Forward buttons 
        /// 
        public string Name 
        { 
            get { return (string)GetValue(NameProperty); }
            set { SetValue(NameProperty, value); } 
        }

        /// 
        /// Attached DependencyProperty for Name property. 
        /// Setting it at the root element of a navigator will update NavWin�s dropdown menu when navigating inside of that navigator.
        ///  
        public static readonly DependencyProperty NameProperty = 
            DependencyProperty.RegisterAttached("Name", typeof(string), typeof(JournalEntry), new PropertyMetadata(String.Empty));
 
        /// 
        /// DependencyProperty for KeepAlive property.
        /// 
        public static readonly DependencyProperty KeepAliveProperty = 
            DependencyProperty.RegisterAttached("KeepAlive", typeof(bool), typeof(JournalEntry), new PropertyMetadata(false));
 
        #endregion 

        // Internal methods 
        /////////////////////////////////////////////////////////////////////

        #region Internal Methods
 
        /// 
        /// Is this journal entry journaling a page function? 
        ///  
        internal virtual bool IsPageFunction()
        { 
            return false;
        }

        ///  
        /// Is this journal entry holding on to a tree?
        ///  
        ///  
        internal virtual bool IsAlive()
        { 
            return false;
        }

        internal virtual void SaveState(object contentObject) 
        {
            if (contentObject == null) 
                throw new ArgumentNullException("contentObject"); 
            if (!IsAlive())
            { 
                if (_jeGroupState.JournalDataStreams != null)
                {
                    Debug.Assert(!_jeGroupState.JournalDataStreams.HasAnyData,
                        "JournalDataSreams should have been emptied by the last RestoreState() call."); 
                }
                else 
                { 
                    _jeGroupState.JournalDataStreams = new DataStreams();
                } 
                _jeGroupState.JournalDataStreams.Save(contentObject);
            }
        }
 
        internal virtual void RestoreState(object contentObject)
        { 
            if (contentObject == null) 
                throw new ArgumentNullException("contentObject");
            if (IsAlive()) 
            {
                Debug.Assert(_jeGroupState.JournalDataStreams == null);
            }
            else 
            {
                DataStreams jds = _jeGroupState.JournalDataStreams; 
                if (jds != null) 
                {
                    jds.Load(contentObject); 
                    // DataStreams not needed anymore. Clear for fresh saving when the next navigation
                    // occurs.
                    jds.Clear();
                } 
            }
        } 
 
        internal virtual bool Navigate(INavigator navigator, NavigationMode navMode)
        { 
            Debug.Assert(navMode == NavigationMode.Back || navMode == NavigationMode.Forward);

            // This is fallback functionality if somebody creates a JournalEntry and gives it a URI.
            if (this.Source != null) 
            {
                return navigator.Navigate(Source, new NavigateInfo(Source, navMode, this)); 
            } 
            else
            { 
                Invariant.Assert(false, "Cannot navigate to a journal entry that does not have a Source.");
                return false;
            }
        } 

        ///  
        /// Returns a string that contains the URI for display in a JournalEntry. 
        /// It removes pack://application:,,,/ and any component, and replaces
        /// pack://siteoforigin:,,,/ with the actual site of origin URI. 
        /// 
        /// The URI to display
        /// The site of origin URI
        /// display name 
        internal static string GetDisplayName(Uri uri, Uri siteOfOrigin)
        { 
            // In case this is a fragment navigation in a tree that was not navigated to by URI... 
            if (!uri.IsAbsoluteUri)
            { 
                return uri.ToString();
            }

            bool isPack = String.Compare(uri.Scheme, PackUriHelper.UriSchemePack, StringComparison.OrdinalIgnoreCase) == 0; 
            string displayName;
 
            if (isPack) 
            {
                Uri relative = BaseUriHelper.MakeRelativeToSiteOfOriginIfPossible(uri); 
                if (! relative.IsAbsoluteUri)
                {
                    displayName = (new Uri(siteOfOrigin, relative)).ToString();
                } 
                else
                { 
                    string relativeUri = uri.AbsolutePath + uri.Query + uri.Fragment; 
                    string part, assy, assyVers, assyKey;
                    BaseUriHelper.GetAssemblyNameAndPart(new Uri(relativeUri, UriKind.Relative), out part, out assy, out assyVers, out assyKey); 
                    if (!string.IsNullOrEmpty(assy))
                    {
                        displayName = part;
                    } 
                    else
                    { 
                        displayName = relativeUri; 
                    }
                } 
            }
            else
            {
                displayName = uri.ToString(); 
            }
 
            if (!string.IsNullOrEmpty(displayName) && displayName[0] == '/') 
            {
                displayName = displayName.Substring(1); 
            }

            return displayName;
        } 
        #endregion
 
        // Internal properties 
        /////////////////////////////////////////////////////////////////////
 
        #region Internal properties

        internal JournalEntryGroupState JEGroupState
        { 
#if DEBUG
            [DebuggerStepThrough] 
#endif 
            get { return _jeGroupState; }
            set { _jeGroupState = value; } 
        }

        /// 
        /// We will now store the entire entry data in the travellog so Journaling will 
        /// work even if you renavigate back to the app from html pages as long as it is
        /// linear history navigations. 
        ///  
        internal int Id
        { 
            get { return _id; }
            set { _id = value; }
        }
 
        /// 
        /// The NavigationService(toplevel || frame) where this entry was last displayed. 
        ///  
        internal Guid NavigationServiceId
        { 
            get { return _jeGroupState.NavigationServiceId; ; }
        }

        ///  
        /// Journal entry type
        ///  
        internal JournalEntryType EntryType 
        {
#if DEBUG 
            [DebuggerStepThrough]
#endif
            get { return _entryType; }
            set { _entryType = value; } 
        }
 
        ///  
        /// Can this be navigated to?
        ///  
        internal bool IsNavigable()
        {
            return _entryType == JournalEntryType.Navigable;
        } 

        internal uint ContentId 
        { 
            get { return _jeGroupState.ContentId; }
        } 

        internal CustomJournalStateInternal RootViewerState
        {
            get { return _rootViewerState; } 
            set { _rootViewerState = value; }
        } 
 
        #endregion
 
        // Private fields
        //
        // If you add any fields here, check if it needs to be serialized.
        // If yes, then add it to the ISerializable implementation and make 
        // corresponding changes in the Serialization constructor.
        // 
        ///////////////////////////////////////////////////////////////////// 

        #region Private fields 
        private int _id;
        private JournalEntryGroupState _jeGroupState;
        /// 
        /// Converted relative to pack://application, if possible 
        /// 
        private Uri _source; 
        private JournalEntryType _entryType = JournalEntryType.Navigable; 
        private CustomContentState _customContentState;
        private CustomJournalStateInternal _rootViewerState; 
        #endregion
    }

    //** 
    //** All derived classes are in MS.Internal.AppModel.
} 

// 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