SinglePageViewer.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Controls / SinglePageViewer.cs / 1305600 / SinglePageViewer.cs

                            //---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
// File: FlowDocumentPageViewer.cs 
//
// Description: FlowDocumentPageViewer provides a simple user experience for viewing 
//              one page of content at a time. The experience is optimized for 
//              FlowDocument scenarios, however any IDocumentPaginatorSource
//              can be viewed using this control. 
//
//---------------------------------------------------------------------------

using System.Collections.ObjectModel;       // ReadOnlyCollection 
using System.Printing;                      // WritingCompletedEventArgs
using System.Windows.Automation.Peers;      // AutomationPeer 
using System.Windows.Documents;             // IDocumentPaginatorSouce, ... 
using System.Windows.Documents.Serialization;  // WritingCompletedEventArgs
using System.Windows.Input;                 // UICommand 
using System.Windows.Media;                 // VisualTreeHelper
using System.Windows.Controls.Primitives;   // DocumentViewerBase, DocumentPageView
using System.Windows.Xps;                   // XpsDocumentWriter
using System.Windows.Threading; 
using MS.Internal;                          // Invariant, DoubleUtil
using MS.Internal.Commands;                 // CommandHelpers 
using MS.Internal.Documents;                // FindToolBar 
using MS.Internal.KnownBoxes;               // BooleanBoxes
using MS.Internal.PresentationFramework;    // SecurityHelper 
using MS.Internal.AppModel;                 // IJournalState
using System.Security;                      // SecurityCritical, SecurityTreatAsSafe

namespace System.Windows.Controls 
{
    ///  
    /// FlowDocumentPageViewer provides a simple user experience for viewing one page 
    /// of content at a time. The experience is optimized for FlowDocument scenarios,
    /// however any IDocumentPaginatorSource can be viewed using this control. 
    /// 
    [TemplatePart(Name = "PART_FindToolBarHost", Type = typeof(Decorator))]
    public class FlowDocumentPageViewer : DocumentViewerBase, IJournalState
    { 
        //-------------------------------------------------------------------
        // 
        //  Constructors 
        //
        //------------------------------------------------------------------- 

        #region Constructors

        ///  
        /// Initializes class-wide settings.
        ///  
        static FlowDocumentPageViewer() 
        {
            DefaultStyleKeyProperty.OverrideMetadata( 
                typeof(FlowDocumentPageViewer),
                new FrameworkPropertyMetadata(new ComponentResourceKey(typeof(PresentationUIStyleResources), "PUIFlowDocumentPageViewer")));

            _dType = DependencyObjectType.FromSystemTypeInternal(typeof(FlowDocumentPageViewer)); 

            TextBoxBase.SelectionBrushProperty.OverrideMetadata(typeof(FlowDocumentPageViewer), 
                new FrameworkPropertyMetadata(new PropertyChangedCallback(UpdateCaretElement))); 
            TextBoxBase.SelectionOpacityProperty.OverrideMetadata(typeof(FlowDocumentPageViewer),
                new FrameworkPropertyMetadata(new PropertyChangedCallback(UpdateCaretElement))); 

            // Create our CommandBindings
            CreateCommandBindings();
 
            EventManager.RegisterClassHandler(typeof(FlowDocumentPageViewer), Keyboard.KeyDownEvent, new KeyEventHandler(KeyDownHandler), true);
        } 
 
        /// 
        /// Instantiates a new instance of a FlowDocumentPageViewer. 
        /// 
        public FlowDocumentPageViewer()
            : base()
        { 
            this.LayoutUpdated += new EventHandler(HandleLayoutUpdated);
        } 
 
        #endregion Constructors
 
        //--------------------------------------------------------------------
        //
        //  Public Methods
        // 
        //-------------------------------------------------------------------
 
        #region Public Methods 

        ///  
        /// Called when the Template's tree has been generated
        /// 
        /// Whether Visuals were added to the tree.
        public override void OnApplyTemplate() 
        {
            base.OnApplyTemplate(); 
 
            // Initialize FindTooBar host.
            // If old FindToolBar is enabled, disable it first to ensure appropriate cleanup. 
            if (FindToolBar != null)
            {
                ToggleFindToolBar(false);
            } 
            _findToolBarHost = GetTemplateChild(_findToolBarHostTemplateName) as Decorator;
        } 
 
        /// 
        /// Increases the current zoom. 
        /// 
        public void IncreaseZoom()
        {
            OnIncreaseZoomCommand(); 
        }
 
        ///  
        /// Decreases the current zoom.
        ///  
        public void DecreaseZoom()
        {
            OnDecreaseZoomCommand();
        } 

        ///  
        /// Invokes the Find Toolbar. This is analogous to the ApplicationCommands.Find. 
        /// 
        public void Find() 
        {
            OnFindCommand();
        }
 
        #endregion Public Methods
 
        //-------------------------------------------------------------------- 
        //
        //  Public Properties 
        //
        //--------------------------------------------------------------------

        #region Public Properties 

        ///  
        /// Text Selection (readonly) 
        /// 
        public TextSelection Selection 
        {
            get
            {
                ITextSelection textSelection = null; 
                FlowDocument flowDocument = Document as FlowDocument;
                if (flowDocument != null) 
                { 
                    textSelection = flowDocument.StructuralCache.TextContainer.TextSelection;
                } 
                return textSelection as TextSelection;
            }
        }
 
        /// 
        /// The Zoom applied to all pages; this value is 100-based. 
        ///  
        public double Zoom
        { 
            get { return (double) GetValue(ZoomProperty); }
            set { SetValue(ZoomProperty, value); }
        }
 
        /// 
        /// The maximum allowed value of the Zoom property. 
        ///  
        public double MaxZoom
        { 
            get { return (double) GetValue(MaxZoomProperty); }
            set { SetValue(MaxZoomProperty, value); }
        }
 
        /// 
        /// The minimum allowed value of the Zoom property. 
        ///  
        public double MinZoom
        { 
            get { return (double) GetValue(MinZoomProperty); }
            set { SetValue(MinZoomProperty, value); }
        }
 
        /// 
        /// The amount the Zoom property is incremented or decremented when 
        /// the IncreaseZoom or DecreaseZoom command is executed. 
        /// 
        public double ZoomIncrement 
        {
            get { return (double) GetValue(ZoomIncrementProperty); }
            set { SetValue(ZoomIncrementProperty, value); }
        } 

        ///  
        /// Whether the viewer can increase the current zoom. 
        /// 
        public virtual bool CanIncreaseZoom 
        {
            get { return (bool) GetValue(CanIncreaseZoomProperty); }
        }
 
        /// 
        /// Whether the viewer can decrease the current zoom. 
        ///  
        public virtual bool CanDecreaseZoom
        { 
            get { return (bool) GetValue(CanDecreaseZoomProperty); }
        }

        ///  
        /// 
        ///  
        public Brush SelectionBrush 
        {
            get { return (Brush)GetValue(SelectionBrushProperty); } 
            set { SetValue(SelectionBrushProperty, value); }
        }

        ///  
        /// 
        ///  
        public double SelectionOpacity 
        {
            get { return (double)GetValue(SelectionOpacityProperty); } 
            set { SetValue(SelectionOpacityProperty, value); }
        }

        #region Public Dynamic Properties 

        ///  
        ///  
        /// 
        public static readonly DependencyProperty ZoomProperty = 
                DependencyProperty.Register(
                        "Zoom",
                        typeof(double),
                        typeof(FlowDocumentPageViewer), 
                        new FrameworkPropertyMetadata(
                                100d, 
                                new PropertyChangedCallback(ZoomChanged), 
                                new CoerceValueCallback(CoerceZoom)),
                        new ValidateValueCallback(ZoomValidateValue)); 

        /// 
        /// 
        ///  
        public static readonly DependencyProperty MaxZoomProperty =
                DependencyProperty.Register( 
                        "MaxZoom", 
                        typeof(double),
                        typeof(FlowDocumentPageViewer), 
                        new FrameworkPropertyMetadata(
                                200d,
                                new PropertyChangedCallback(MaxZoomChanged),
                                new CoerceValueCallback(CoerceMaxZoom)), 
                        new ValidateValueCallback(ZoomValidateValue));
 
        ///  
        /// 
        ///  
        public static readonly DependencyProperty MinZoomProperty =
                DependencyProperty.Register(
                        "MinZoom",
                        typeof(double), 
                        typeof(FlowDocumentPageViewer),
                        new FrameworkPropertyMetadata( 
                                80d, 
                                new PropertyChangedCallback(MinZoomChanged)),
                        new ValidateValueCallback(ZoomValidateValue)); 

        /// 
        /// 
        ///  
        public static readonly DependencyProperty ZoomIncrementProperty =
                DependencyProperty.Register( 
                        "ZoomIncrement", 
                        typeof(double),
                        typeof(FlowDocumentPageViewer), 
                        new FrameworkPropertyMetadata(10d),
                        new ValidateValueCallback(ZoomValidateValue));

        ///  
        /// 
        ///  
        protected static readonly DependencyPropertyKey CanIncreaseZoomPropertyKey = 
                DependencyProperty.RegisterReadOnly(
                        "CanIncreaseZoom", 
                        typeof(bool),
                        typeof(FlowDocumentPageViewer),
                        new FrameworkPropertyMetadata(true));
 
        /// 
        ///  
        ///  
        public static readonly DependencyProperty CanIncreaseZoomProperty = CanIncreaseZoomPropertyKey.DependencyProperty;
 
        /// 
        /// 
        /// 
        protected static readonly DependencyPropertyKey CanDecreaseZoomPropertyKey = 
                DependencyProperty.RegisterReadOnly(
                        "CanDecreaseZoom", 
                        typeof(bool), 
                        typeof(FlowDocumentPageViewer),
                        new FrameworkPropertyMetadata(true)); 

        /// 
        /// 
        ///  
        public static readonly DependencyProperty CanDecreaseZoomProperty =
                CanDecreaseZoomPropertyKey.DependencyProperty; 
 
        /// 
        ///  
        /// 
        public static readonly DependencyProperty SelectionBrushProperty =
            TextBoxBase.SelectionBrushProperty.AddOwner(typeof(FlowDocumentPageViewer));
 
        /// 
        ///  
        ///  
        public static readonly DependencyProperty SelectionOpacityProperty =
            TextBoxBase.SelectionOpacityProperty.AddOwner(typeof(FlowDocumentPageViewer)); 


        #endregion Public Dynamic Properties
 
        #endregion Public Properties
 
        //------------------------------------------------------------------- 
        //
        //  Protected Methods 
        //
        //--------------------------------------------------------------------

        #region Protected Methods 

        ///  
        /// Creates AutomationPeer () 
        /// 
        protected override AutomationPeer OnCreateAutomationPeer() 
        {
            return new FlowDocumentPageViewerAutomationPeer(this);
        }
 
        /// 
        /// This is the method that responds to the KeyDown event. 
        ///  
        /// Event arguments
        ///  
        /// Critical: get_SearchUp is defined in a non-APTCA assembly.
        /// TreatAsSafe: call to get_SearchUp does not entail any risk.
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        protected override void OnKeyDown(KeyEventArgs e)
        { 
            // Esc -- Close FindToolBar 
            if (e.Key == Key.Escape)
            { 
                if (FindToolBar != null)
                {
                    ToggleFindToolBar(false);
                    e.Handled = true; 
                }
            } 
 
            // F3 -- Invoke Find
            if (e.Key == Key.F3) 
            {
                if (CanShowFindToolBar)
                {
                    if (FindToolBar != null) 
                    {
                        // If the Shift key is also pressed, then search up. 
                        FindToolBar.SearchUp = ((e.KeyboardDevice.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift); 
                        OnFindInvoked(this, EventArgs.Empty);
                    } 
                    else
                    {
                        // Make the FindToolbar visible
                        ToggleFindToolBar(true); 
                    }
                    e.Handled = true; 
                } 
            }
 
            // If not handled, do default handling.
            if (!e.Handled)
            {
                base.OnKeyDown(e); 
            }
        } 
 
        /// 
        /// An event reporting a mouse wheel rotation. 
        /// 
        protected override void OnMouseWheel(MouseWheelEventArgs e)
        {
            // [Mouse Wheel + Control] - zooming 
            // [Mouse Wheel] - page navigation
            if (e.Delta != 0) 
            { 
                if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
                { 
                    if (e.Delta > 0)
                    {
                        IncreaseZoom();
                    } 
                    else
                    { 
                        DecreaseZoom(); 
                    }
                } 
                else
                {
                    if (e.Delta > 0)
                    { 
                        PreviousPage();
                    } 
                    else 
                    {
                        NextPage(); 
                    }
                }
                e.Handled = false;
            } 

            // If not handled, do default handling. 
            if (!e.Handled) 
            {
                base.OnMouseWheel(e); 
            }
        }

        ///  
        /// Called when ContextMenuOpening is raised on this element.
        ///  
        /// Event arguments 
        protected override void OnContextMenuOpening(ContextMenuEventArgs e)
        { 
            base.OnContextMenuOpening(e);
            DocumentViewerHelper.OnContextMenuOpening(Document as FlowDocument, this, e);
        }
 
        /// 
        /// Called when the PageViews collection is modified; this occurs when GetPageViewsCollection 
        /// returns True or if the control's template is modified. 
        /// 
        protected override void OnPageViewsChanged() 
        {
            // Change of DocumentPageView collection resets current ContentPosition.
            // This position is updated when layout process is done.
            _contentPosition = null; 

            // Apply zoom value to new DocumentPageViews 
            ApplyZoom(); 

            base.OnPageViewsChanged(); 
        }

        /// 
        /// Called when the Document property is changed. 
        /// 
        protected override void OnDocumentChanged() 
        { 
            // Document change resets current ContentPosition.
            _contentPosition = null; 

            // _oldDocument is cached from previous document changed notification.
            if (_oldDocument != null)
            { 
                DynamicDocumentPaginator dynamicDocumentPaginator = _oldDocument.DocumentPaginator as DynamicDocumentPaginator;
                if (dynamicDocumentPaginator != null) 
                { 
                    dynamicDocumentPaginator.GetPageNumberCompleted -= new GetPageNumberCompletedEventHandler(HandleGetPageNumberCompleted);
                } 

                FlowDocumentPaginator flowDocumentPaginator = _oldDocument.DocumentPaginator as FlowDocumentPaginator;
                if (flowDocumentPaginator != null)
                { 
                    flowDocumentPaginator.BreakRecordTableInvalidated -= new BreakRecordTableInvalidatedEventHandler(HandleAllBreakRecordsInvalidated);
                } 
            } 

            base.OnDocumentChanged(); 
            _oldDocument = Document;

            // Validate the new document type
            if (Document != null && !(Document is FlowDocument)) 
            {
                // Undo new document assignment. 
                Document = null; 
                // Throw exception.
                throw new NotSupportedException(SR.Get(SRID.FlowDocumentPageViewerOnlySupportsFlowDocument)); 
            }

            if(Document != null)
            { 
                DynamicDocumentPaginator dynamicDocumentPaginator = Document.DocumentPaginator as DynamicDocumentPaginator;
                if (dynamicDocumentPaginator != null) 
                { 
                    dynamicDocumentPaginator.GetPageNumberCompleted += new GetPageNumberCompletedEventHandler(HandleGetPageNumberCompleted);
                } 

                FlowDocumentPaginator flowDocumentPaginator = Document.DocumentPaginator as FlowDocumentPaginator;
                if (flowDocumentPaginator != null)
                { 
                    flowDocumentPaginator.BreakRecordTableInvalidated += new BreakRecordTableInvalidatedEventHandler(HandleAllBreakRecordsInvalidated);
                } 
            } 

            // Update the toolbar with our current document state. 
            if (!CanShowFindToolBar)
            {
                // Disable FindToolBar, if the content does not support it.
                if (FindToolBar != null) 
                {
                    ToggleFindToolBar(false); 
                } 
            }
 
            // Go to the first page of new content.
            OnGoToPageCommand(1);
        }
 
        /// 
        /// Called when print has been completed. 
        ///  
        protected virtual void OnPrintCompleted()
        { 
            ClearPrintingState();
        }

        ///  
        /// Handler for the PreviousPage command.
        ///  
        protected override void OnPreviousPageCommand() 
        {
            if (this.CanGoToPreviousPage) 
            {
                // Page navigation resets current ContentPosition.
                // This position is updated when layout process is done.
                _contentPosition = null; 

                base.OnPreviousPageCommand(); 
            } 
        }
 
        /// 
        /// Handler for the NextPage command.
        /// 
        protected override void OnNextPageCommand() 
        {
            if (this.CanGoToNextPage) 
            { 
                // Page navigation resets current ContentPosition.
                // This position is updated when layout process is done. 
                _contentPosition = null;

                base.OnNextPageCommand();
            } 
        }
 
        ///  
        /// Handler for the FirstPage command.
        ///  
        protected override void OnFirstPageCommand()
        {
            if (this.CanGoToPreviousPage)
            { 
                // Page navigation resets current ContentPosition.
                // This position is updated when layout process is done. 
                _contentPosition = null; 

                base.OnFirstPageCommand(); 
            }
        }

        ///  
        /// Handler for the LastPage command.
        ///  
        protected override void OnLastPageCommand() 
        {
            if (this.CanGoToNextPage) 
            {
                // Page navigation resets current ContentPosition.
                // This position is updated when layout process is done.
                _contentPosition = null; 

                base.OnLastPageCommand(); 
            } 
        }
 
        /// 
        /// Handler for the GoToPage command.
        /// 
        protected override void OnGoToPageCommand(int pageNumber) 
        {
            if (CanGoToPage(pageNumber) && this.MasterPageNumber != pageNumber) 
            { 
                // Page navigation resets current ContentPosition.
                // This position is updated when layout process is done. 
                _contentPosition = null;

                base.OnGoToPageCommand(pageNumber);
            } 
        }
 
        ///  
        /// Handler for the Find command.
        ///  
        protected virtual void OnFindCommand()
        {
            if (CanShowFindToolBar)
            { 
                // Toggle on the FindToolBar between visible and hidden state.
                ToggleFindToolBar(FindToolBar == null); 
            } 
        }
 
        /// 
        /// Handler for the Print command.
        /// 
        protected override void OnPrintCommand() 
        {
#if !DONOTREFPRINTINGASMMETA 
            XpsDocumentWriter docWriter; 
            PrintDocumentImageableArea ia = null;
            FlowDocumentPaginator paginator; 
            FlowDocument document = Document as FlowDocument;
            Thickness pagePadding;

            // Only one printing job is allowed. 
            if (_printingState != null)
            { 
                return; 
            }
 
            // If the document is FlowDocument, do custom printing. Otherwise go through default path.
            if (document != null)
            {
                // Show print dialog. 
                docWriter = PrintQueue.CreateXpsDocumentWriter(ref ia);
                if (docWriter != null && ia != null) 
                { 
                    // Store the current state of the document in the PrintingState
                    paginator = ((IDocumentPaginatorSource)document).DocumentPaginator as FlowDocumentPaginator; 
                    _printingState = new FlowDocumentPrintingState();
                    _printingState.XpsDocumentWriter = docWriter;
                    _printingState.PageSize = paginator.PageSize;
                    _printingState.PagePadding = document.PagePadding; 
                    _printingState.IsSelectionEnabled = IsSelectionEnabled;
 
                    // Since _printingState value is used to determine CanExecute state, we must invalidate that state. 
                    CommandManager.InvalidateRequerySuggested();
 
                    // Register for XpsDocumentWriter events.
                    docWriter.WritingCompleted += new WritingCompletedEventHandler(HandlePrintCompleted);
                    docWriter.WritingCancelled += new WritingCancelledEventHandler(HandlePrintCancelled);
 
                    // Add PreviewCanExecute handler to have a chance to disable UI Commands during printing.
                    CommandManager.AddPreviewCanExecuteHandler(this, new CanExecuteRoutedEventHandler(PreviewCanExecuteRoutedEventHandler)); 
 
                    // Suspend layout on DocumentPageViews.
                    ReadOnlyCollection pageViews = PageViews; 
                    for (int index = 0; index < pageViews.Count; index++)
                    {
                        pageViews[index].SuspendLayout();
                    } 

                    // Disable TextSelection, if currently enabled. 
                    if (IsSelectionEnabled) 
                    {
                        IsSelectionEnabled = false; 
                    }

                    // Change the PageSize and PagePadding for the document to match the CanvasSize for the printer device.
                    paginator.PageSize = new Size(ia.MediaSizeWidth, ia.MediaSizeHeight); 
                    pagePadding = document.ComputePageMargin();
                    document.PagePadding = new Thickness( 
                        Math.Max(ia.OriginWidth, pagePadding.Left), 
                        Math.Max(ia.OriginHeight, pagePadding.Top),
                        Math.Max(ia.MediaSizeWidth - (ia.OriginWidth + ia.ExtentWidth), pagePadding.Right), 
                        Math.Max(ia.MediaSizeHeight - (ia.OriginHeight + ia.ExtentHeight), pagePadding.Bottom));

                    // Send DocumentPaginator to the printer.
                    docWriter.WriteAsync(paginator); 
                }
            } 
            else 
            {
                base.OnPrintCommand(); 
            }
#endif // DONOTREFPRINTINGASMMETA
        }
 
        /// 
        /// Handler for the CancelPrint command. 
        ///  
        protected override void OnCancelPrintCommand()
        { 
#if !DONOTREFPRINTINGASMMETA
            if (_printingState != null)
            {
                _printingState.XpsDocumentWriter.CancelAsync(); 
            }
            else 
            { 
                base.OnCancelPrintCommand();
            } 
#endif // DONOTREFPRINTINGASMMETA
        }

        ///  
        /// Handler for the IncreaseZoom command.
        ///  
        protected virtual void OnIncreaseZoomCommand() 
        {
            // If can zoom in, increase zoom by the zoom increment value. 
            if (this.CanIncreaseZoom)
            {
                SetCurrentValueInternal(ZoomProperty, Math.Min(Zoom + ZoomIncrement, MaxZoom));
            } 
        }
 
        ///  
        /// Handler for the DecreaseZoom command.
        ///  
        protected virtual void OnDecreaseZoomCommand()
        {
            // If can zoom out, decrease zoom by the zoom increment value.
            if (this.CanDecreaseZoom) 
            {
                SetCurrentValueInternal(ZoomProperty, Math.Max(Zoom - ZoomIncrement, MinZoom)); 
            } 
        }
 
        #endregion Protected Methods

        //-------------------------------------------------------------------
        // 
        //  Internal Methods
        // 
        //------------------------------------------------------------------- 

        #region Internal Methods 

        /// 
        /// Allows FrameworkElement to augment the EventRoute.
        ///  
        internal override bool BuildRouteCore(EventRoute route, RoutedEventArgs args)
        { 
            // If FlowDocumentPageViewer is used as embedded viewer (in FlowDocumentReader), 
            // it is not part of logical tree, so default logic in FE to re-add logical
            // tree from branched node does not work here. 
            // But before FlowDocumentPageViewer is added to the event route, logical
            // ancestors up to Document need to be added to the route. Otherwise
            // content will not have a chance to react to events first.
            // This breaks navigation cursor management logic, because TextEditor attached 
            // to FlowDocumentPageViewer handles those events first.
            DependencyObject document = this.Document as DependencyObject; 
            if (document != null && LogicalTreeHelper.GetParent(document) != this) 
            {
                DependencyObject branchNode = route.PeekBranchNode() as DependencyObject; 
                if (branchNode != null && DocumentViewerHelper.IsLogicalDescendent(branchNode, document))
                {
                    // Add intermediate ContentElements to the route.
                    FrameworkElement.AddIntermediateElementsToRoute( 
                        LogicalTreeHelper.GetParent(document), route, args, LogicalTreeHelper.GetParent(branchNode));
                } 
            } 
            return base.BuildRouteCore(route, args);
        } 

        /// 
        /// Brings specified point into view.
        ///  
        /// Point in the viewer's coordinate system.
        /// Whether operation is pending or not. 
        ///  
        /// It is guaranteed that Point is not over any existing pages.
        ///  
        internal bool BringPointIntoView(Point point)
        {
            int index;
            Rect[] pageRects; 
            Rect pageRect;
            ReadOnlyCollection pageViews = this.PageViews; 
            bool bringIntoViewPending = false; 

            if (pageViews.Count > 0) 
            {
                // Calculate rectangles for all pages.
                pageRects = new Rect[pageViews.Count];
                for (index = 0; index < pageViews.Count; index++) 
                {
                    pageRect = new Rect(pageViews[index].RenderSize); 
                    pageRect = pageViews[index].TransformToAncestor(this).TransformBounds(pageRect); 
                    pageRects[index] = pageRect;
                } 

                // Try to find exact hit
                for (index = 0; index < pageRects.Length; index++)
                { 
                    if (pageRects[index].Contains(point))
                    { 
                        break; 
                    }
                } 

                if (index >= pageRects.Length)
                {
                    // Union all rects. 
                    pageRect = pageRects[0];
                    for (index = 1; index < pageRects.Length; index++) 
                    { 
                        pageRect.Union(pageRects[index]);
                    } 
                    //
                    if (DoubleUtil.LessThan(point.X, pageRect.Left))
                    {
                        if (this.CanGoToPreviousPage) 
                        {
                            OnPreviousPageCommand(); 
                            bringIntoViewPending = true; 
                        }
                    } 
                    else if (DoubleUtil.GreaterThan(point.X, pageRect.Right))
                    {
                        if (this.CanGoToNextPage)
                        { 
                            OnNextPageCommand();
                            bringIntoViewPending = true; 
                        } 
                    }
                    else if (DoubleUtil.LessThan(point.Y, pageRect.Top)) 
                    {
                        if (this.CanGoToPreviousPage)
                        {
                            OnPreviousPageCommand(); 
                            bringIntoViewPending = true;
                        } 
                    } 
                    else if (DoubleUtil.GreaterThan(point.Y, pageRect.Bottom))
                    { 
                        if (this.CanGoToNextPage)
                        {
                            OnNextPageCommand();
                            bringIntoViewPending = true; 
                        }
                    } 
                } 
            }
 
            return bringIntoViewPending;
        }

        ///  
        /// Bring specified content position into view.
        ///  
        internal object BringContentPositionIntoView(object arg) 
        {
            PrivateBringContentPositionIntoView(arg, false); 

            return null;
        }
 
        #endregion Internal Methods
 
        //------------------------------------------------------------------- 
        //
        //  Internal Properties 
        //
        //--------------------------------------------------------------------

        #region Internal Properties 

        ///  
        /// ContentPosition representing currently viewed content. 
        /// 
        internal ContentPosition ContentPosition 
        {
            get { return _contentPosition; }
        }
 
        /// 
        /// Whether FindToolBar can be enabled. 
        ///  
        internal bool CanShowFindToolBar
        { 
            get { return (_findToolBarHost != null && this.Document != null && this.TextEditor != null); }
        }

        ///  
        /// Whether currently printing the content.
        ///  
        internal bool IsPrinting 
        {
            get { return (_printingState != null); } 
        }

        #endregion Internal Properties
 
        //-------------------------------------------------------------------
        // 
        //  Private Methods 
        //
        //-------------------------------------------------------------------- 

        #region Private Methods

        ///  
        /// Handler for LayoutUpdated event raised by the LayoutSystem.
        ///  
        private void HandleLayoutUpdated(object sender, EventArgs e) 
        {
            DocumentPageView masterPageView; 
            DynamicDocumentPaginator documentPaginator;

            // Ignore LayoutUpdated during printing.
            if (this.Document != null && _printingState == null) 
            {
                documentPaginator = this.Document.DocumentPaginator as DynamicDocumentPaginator; 
                if (documentPaginator != null) 
                {
                    // Update ContentPosition, if not cached. 
                    if (_contentPosition == null)
                    {
                        masterPageView = GetMasterPageView();
                        if (masterPageView != null && masterPageView.DocumentPage != null) 
                        {
                            _contentPosition = documentPaginator.GetPagePosition(masterPageView.DocumentPage); 
                        } 
                        if (_contentPosition == ContentPosition.Missing)
                        { 
                            _contentPosition = null;
                        }
                    }
                    // Otherwise bring this position into view. 
                    else
                    { 
                        PrivateBringContentPositionIntoView(_contentPosition, true); 
                    }
                } 
            }
        }

        ///  
        /// Handler for GetPageNumberCompleted event raised by the Document.
        ///  
        private void HandleGetPageNumberCompleted(object sender, GetPageNumberCompletedEventArgs e) 
        {
            if (Document != null && sender == Document.DocumentPaginator && e != null) 
            {
                if (!e.Cancelled && e.Error == null && e.UserState == _bringContentPositionIntoViewToken)
                {
                    int newMasterPageNumber = e.PageNumber + 1; 

                    OnGoToPageCommand(newMasterPageNumber); 
                } 
            }
        } 

        /// 
        /// Handler for BreakRecordTableInvalidated event raised by the Paginator.
        ///  
        private void HandleAllBreakRecordsInvalidated(object sender, EventArgs e)
        { 
            ReadOnlyCollection pageViews = PageViews; 
            for (int index = 0; index < pageViews.Count; index++)
            { 
                pageViews[index].DuplicateVisual();
            }
        }
 
        /// 
        /// Handle the case when the position is no longer valid for the current document, conservatively returns true if 
        /// is uknown. 
        /// 
        private bool IsValidContentPositionForDocument(IDocumentPaginatorSource document, ContentPosition contentPosition) 
        {
            FlowDocument flowDocument = document as FlowDocument;
            TextPointer textPointer = contentPosition as TextPointer;
 
            if(flowDocument != null && textPointer != null)
            { 
                return flowDocument.ContentStart.TextContainer == textPointer.TextContainer; 
            }
 
            return true;
        }

        ///  
        /// Bring specified content position into view. (If async, cancel any previous async request to bring into view.)
        ///  
        private void PrivateBringContentPositionIntoView(object arg, bool isAsyncRequest) 
        {
            ContentPosition contentPosition = arg as ContentPosition; 
            if (contentPosition != null && Document != null)
            {
                DynamicDocumentPaginator documentPaginator = this.Document.DocumentPaginator as DynamicDocumentPaginator;
                if (documentPaginator != null && IsValidContentPositionForDocument(Document, contentPosition)) 
                {
                    documentPaginator.CancelAsync(_bringContentPositionIntoViewToken); 
 
                    if(isAsyncRequest)
                    { 
                        documentPaginator.GetPageNumberAsync(contentPosition, _bringContentPositionIntoViewToken);
                    }
                    else
                    { 
                        int newMasterPageNumber = documentPaginator.GetPageNumber(contentPosition) + 1;
 
                        OnGoToPageCommand(newMasterPageNumber); 
                    }
 
                    _contentPosition = contentPosition;
                }
            }
        } 

        ///  
        /// Called when WritingCompleted event raised by a DocumentWriter (during printing). 
        /// 
        /// Sender of the event. 
        /// Event arguments.
        private void HandlePrintCompleted(object sender, WritingCompletedEventArgs e)
        {
            OnPrintCompleted(); 
        }
 
        ///  
        /// Called when WritingCancelled event raised by a DocumentWriter (during printing).
        ///  
        /// Sender of the event.
        /// Event arguments.
        private void HandlePrintCancelled(object sender, WritingCancelledEventArgs e)
        { 
            ClearPrintingState();
        } 
 
        /// 
        /// Clears printing state. 
        /// 
        private void ClearPrintingState()
        {
#if !DONOTREFPRINTINGASMMETA 
            if (_printingState != null)
            { 
                // Resume layout on DocumentPageViews. 
                ReadOnlyCollection pageViews = PageViews;
                for (int index = 0; index < pageViews.Count; index++) 
                {
                    pageViews[index].ResumeLayout();
                }
 
                // Enable TextSelection, if it was previously enabled.
                if (_printingState.IsSelectionEnabled) 
                { 
                    IsSelectionEnabled = true;
                } 

                // Remove PreviewCanExecute handler (added when Print command was executed).
                CommandManager.RemovePreviewCanExecuteHandler(this, new CanExecuteRoutedEventHandler(PreviewCanExecuteRoutedEventHandler));
 
                // Unregister for XpsDocumentWriter events.
                _printingState.XpsDocumentWriter.WritingCompleted -= new WritingCompletedEventHandler(HandlePrintCompleted); 
                _printingState.XpsDocumentWriter.WritingCancelled -= new WritingCancelledEventHandler(HandlePrintCancelled); 

                // Restore old page metrics on FlowDocument. 
                ((FlowDocument)Document).PagePadding = _printingState.PagePadding;
                Document.DocumentPaginator.PageSize = _printingState.PageSize;

                _printingState = null; 
                // Since _documentWriter value is used to determine CanExecute state, we must invalidate that state.
                CommandManager.InvalidateRequerySuggested(); 
            } 
#endif // DONOTREFPRINTINGASMMETA
        } 

        /// 
        /// Apply zoom value to all existing DocumentPageViews.
        ///  
        private void ApplyZoom()
        { 
            int index; 
            ReadOnlyCollection pageViews;
 
            // Apply zoom value to all DocumentPageViews.
            pageViews = this.PageViews;
            for (index = 0; index < pageViews.Count; index++)
            { 
                pageViews[index].SetPageZoom(Zoom / 100.0);
            } 
        } 

        ///  
        /// Enables/disables the FindToolbar.
        /// 
        /// Whether to enable/disable FindToolBar.
        private void ToggleFindToolBar(bool enable) 
        {
            Invariant.Assert(enable == (FindToolBar == null)); 
            DocumentViewerHelper.ToggleFindToolBar(_findToolBarHost, new EventHandler(OnFindInvoked), enable); 
        }
 
        /// 
        /// Invoked when the "Find" button in the Find Toolbar is clicked.
        /// This method invokes the actual Find process.
        ///  
        /// The object that sent this event
        /// The Click Events associated with this event 
        private void OnFindInvoked(object sender, EventArgs e) 
        {
            ITextRange findResult; 
            int newMasterPageNumber;
            FindToolBar findToolBar = FindToolBar;

            if (findToolBar != null && this.TextEditor != null) 
            {
                // In order to show current text selection TextEditor requires Focus to be set on the UIScope. 
                // If there embedded controls, it may happen that embedded control currently has focus and find 
                // was invoked through hotkeys. To support this case we manually move focus to the appropriate element.
                Focus(); 

                findResult = Find(findToolBar);

                // If we found something, bring it into the view. Otherwise alert the user. 
                if ((findResult != null) && (!findResult.IsEmpty))
                { 
                    if (findResult.Start is ContentPosition) 
                    {
                        // Bring find result into view. Set also _contentPosition to the beginning of the 
                        // result, so it is visible during resizing.
                        _contentPosition = (ContentPosition)findResult.Start;
                        newMasterPageNumber = ((DynamicDocumentPaginator)this.Document.DocumentPaginator).GetPageNumber(_contentPosition) + 1;
                        OnBringIntoView(this, Rect.Empty, newMasterPageNumber); 
                    }
                } 
                else 
                {
                    DocumentViewerHelper.ShowFindUnsuccessfulMessage(findToolBar); 
                }
            }
        }
 
        /// 
        /// The Zoom has changed and needs to be updated. 
        ///  
        private void ZoomChanged(double oldValue, double newValue)
        { 
            if (!DoubleUtil.AreClose(oldValue, newValue))
            {
                UpdateCanIncreaseZoom();
                UpdateCanDecreaseZoom(); 

                // Changes to Zoom may potentially cause content reflowing. 
                // In such case Paginator will notify DocumentViewerBase 
                // about content changes through PagesChanged event and viewer
                // will invalidate appropriate properties. 
                // Hence there is no need to invalidate any properties on
                // DocumentViewerBase right now.
                ApplyZoom();
            } 
        }
 
        ///  
        /// Update CanIncreaseZoom property.
        ///  
        private void UpdateCanIncreaseZoom()
        {
            SetValue(CanIncreaseZoomPropertyKey, BooleanBoxes.Box(DoubleUtil.GreaterThan(MaxZoom, Zoom)));
        } 

        ///  
        /// Update CanDecreaseZoom property. 
        /// 
        private void UpdateCanDecreaseZoom() 
        {
            SetValue(CanDecreaseZoomPropertyKey, BooleanBoxes.Box(DoubleUtil.LessThan(MinZoom, Zoom)));
        }
 
        /// 
        /// The MaxZoom has changed and needs to be updated. 
        ///  
        private void MaxZoomChanged(double oldValue, double newValue)
        { 
            CoerceValue(ZoomProperty);
            UpdateCanIncreaseZoom();
        }
 
        /// 
        /// The MinZoom has changed and needs to be updated. 
        ///  
        private void MinZoomChanged(double oldValue, double newValue)
        { 
            CoerceValue(MaxZoomProperty);
            CoerceValue(ZoomProperty);
            UpdateCanIncreaseZoom();
            UpdateCanDecreaseZoom(); 
        }
 
        #region Commands 

        ///  
        /// Set up Command and RoutedCommand bindings.
        /// 
        private static void CreateCommandBindings()
        { 
            ExecutedRoutedEventHandler executedHandler;
            CanExecuteRoutedEventHandler canExecuteHandler; 
 
            // Create our generic ExecutedRoutedEventHandler.
            executedHandler = new ExecutedRoutedEventHandler(ExecutedRoutedEventHandler); 
            // Create our generic CanExecuteRoutedEventHandler
            canExecuteHandler = new CanExecuteRoutedEventHandler(CanExecuteRoutedEventHandler);

            // Command: ApplicationCommands.Find 
            CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentPageViewer), ApplicationCommands.Find,
                executedHandler, canExecuteHandler); 
 
            // Command: NavigationCommands.IncreaseZoom
            CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentPageViewer), NavigationCommands.IncreaseZoom, 
                executedHandler, canExecuteHandler, new KeyGesture(Key.OemPlus, ModifierKeys.Control));

            // Command: NavigationCommands.DecreaseZoom
            CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentPageViewer), NavigationCommands.DecreaseZoom, 
                executedHandler, canExecuteHandler, new KeyGesture(Key.OemMinus, ModifierKeys.Control));
 
            // Register input bindings 
            CommandManager.RegisterClassInputBinding(typeof(FlowDocumentPageViewer), new InputBinding(NavigationCommands.PreviousPage, new KeyGesture(Key.Left)));
            CommandManager.RegisterClassInputBinding(typeof(FlowDocumentPageViewer), new InputBinding(NavigationCommands.PreviousPage, new KeyGesture(Key.Up))); 
            CommandManager.RegisterClassInputBinding(typeof(FlowDocumentPageViewer), new InputBinding(NavigationCommands.PreviousPage, new KeyGesture(Key.PageUp)));
            CommandManager.RegisterClassInputBinding(typeof(FlowDocumentPageViewer), new InputBinding(NavigationCommands.NextPage, new KeyGesture(Key.Right)));
            CommandManager.RegisterClassInputBinding(typeof(FlowDocumentPageViewer), new InputBinding(NavigationCommands.NextPage, new KeyGesture(Key.Down)));
            CommandManager.RegisterClassInputBinding(typeof(FlowDocumentPageViewer), new InputBinding(NavigationCommands.NextPage, new KeyGesture(Key.PageDown))); 
            CommandManager.RegisterClassInputBinding(typeof(FlowDocumentPageViewer), new InputBinding(NavigationCommands.FirstPage, new KeyGesture(Key.Home)));
            CommandManager.RegisterClassInputBinding(typeof(FlowDocumentPageViewer), new InputBinding(NavigationCommands.FirstPage, new KeyGesture(Key.Home, ModifierKeys.Control))); 
            CommandManager.RegisterClassInputBinding(typeof(FlowDocumentPageViewer), new InputBinding(NavigationCommands.LastPage, new KeyGesture(Key.End))); 
            CommandManager.RegisterClassInputBinding(typeof(FlowDocumentPageViewer), new InputBinding(NavigationCommands.LastPage, new KeyGesture(Key.End, ModifierKeys.Control)));
        } 

        /// 
        /// Central handler for CanExecuteRouted events fired by Commands directed at FlowDocumentPageViewer.
        ///  
        /// The target of this Command, expected to be FlowDocumentPageViewer
        /// The event arguments for this event. 
        private static void CanExecuteRoutedEventHandler(object target, CanExecuteRoutedEventArgs args) 
        {
            FlowDocumentPageViewer fdpv = target as FlowDocumentPageViewer; 
            Invariant.Assert(fdpv != null, "Target of QueryEnabledEvent must be FlowDocumentPageViewer.");
            Invariant.Assert(args != null, "args cannot be null.");

            // DocumentViewerBase is capable of execution of the majority of its commands. 
            // Special rules:
            // a) Find command is enabled when Document is attached and printing is not in progress. 
            if (args.Command == ApplicationCommands.Find) 
            {
                args.CanExecute = fdpv.CanShowFindToolBar; 
            }
            else
            {
                args.CanExecute = true; 
            }
        } 
 
        /// 
        /// Central handler for all ExecutedRouted events fired by Commands directed at FlowDocumentPageViewer. 
        /// 
        /// The target of this Command, expected to be FlowDocumentPageViewer.
        /// The event arguments associated with this event.
        private static void ExecutedRoutedEventHandler(object target, ExecutedRoutedEventArgs args) 
        {
            FlowDocumentPageViewer fdpv = target as FlowDocumentPageViewer; 
            Invariant.Assert(fdpv != null, "Target of ExecuteEvent must be FlowDocumentPageViewer."); 
            Invariant.Assert(args != null, "args cannot be null.");
 
            // Now we execute the method corresponding to the Command that fired this event;
            // each Command has its own protected virtual method that performs the operation
            // corresponding to the Command.
            if (args.Command == NavigationCommands.IncreaseZoom) 
            {
                fdpv.OnIncreaseZoomCommand(); 
            } 
            else if (args.Command == NavigationCommands.DecreaseZoom)
            { 
                fdpv.OnDecreaseZoomCommand();
            }
            else if (args.Command == ApplicationCommands.Find)
            { 
                fdpv.OnFindCommand();
            } 
            else 
            {
                Invariant.Assert(false, "Command not handled in ExecutedRoutedEventHandler."); 
            }
        }

        ///  
        /// Disable commands on DocumentViewerBase when this printing is in progress.
        ///  
        private void PreviewCanExecuteRoutedEventHandler(object target, CanExecuteRoutedEventArgs args) 
        {
            FlowDocumentPageViewer fdpv = target as FlowDocumentPageViewer; 
            Invariant.Assert(fdpv != null, "Target of PreviewCanExecuteRoutedEventHandler must be FlowDocumentPageViewer.");
            Invariant.Assert(args != null, "args cannot be null.");

            // Disable UI commands, if printing is in progress. 
            if (fdpv._printingState != null)
            { 
                if (args.Command != ApplicationCommands.CancelPrint) 
                {
                    args.CanExecute = false; 
                    args.Handled = true;
                }
            }
        } 

        ///  
        /// Called when a key event occurs. 
        /// 
        private static void KeyDownHandler(object sender, KeyEventArgs e) 
        {
            DocumentViewerHelper.KeyDownHelper(e, ((FlowDocumentPageViewer)sender)._findToolBarHost);
        }
 
        #endregion Commands
 
        #region Static Methods 

        ///  
        /// Coerce the value for Zoom property.
        /// 
        private static object CoerceZoom(DependencyObject d, object value)
        { 
            Invariant.Assert(d != null && d is FlowDocumentPageViewer);
 
            double maxZoom, minZoom; 
            FlowDocumentPageViewer v = (FlowDocumentPageViewer) d;
            double zoom = (double)value; 

            maxZoom = v.MaxZoom;
            if (DoubleUtil.LessThan(maxZoom, zoom))
            { 
                return maxZoom;
            } 
 
            minZoom = v.MinZoom;
            if (DoubleUtil.GreaterThan(minZoom, zoom)) 
            {
                return minZoom;
            }
 
            return value;
        } 
 
        /// 
        /// Coerce the value for MaxZoom property. 
        /// 
        private static object CoerceMaxZoom(DependencyObject d, object value)
        {
            Invariant.Assert(d != null && d is FlowDocumentPageViewer); 

            FlowDocumentPageViewer v = (FlowDocumentPageViewer) d; 
            double minZoom = v.MinZoom; 
            if (DoubleUtil.LessThan((double)value, minZoom))
            { 
                return minZoom;
            }
            return value;
        } 

        ///  
        /// The Zoom has changed and needs to be updated. 
        /// 
        private static void ZoomChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            Invariant.Assert(d != null && d is FlowDocumentPageViewer);
            ((FlowDocumentPageViewer)d).ZoomChanged((double) e.OldValue, (double) e.NewValue);
        } 

        ///  
        /// The MaxZoom has changed and needs to be updated. 
        /// 
        private static void MaxZoomChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            Invariant.Assert(d != null && d is FlowDocumentPageViewer);
            ((FlowDocumentPageViewer)d).MaxZoomChanged((double) e.OldValue, (double) e.NewValue);
        } 

        ///  
        /// The MinZoom has changed and needs to be updated. 
        /// 
        private static void MinZoomChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            Invariant.Assert(d != null && d is FlowDocumentPageViewer);
            ((FlowDocumentPageViewer)d).MinZoomChanged((double) e.OldValue, (double) e.NewValue);
        } 

        ///  
        /// Validate Zoom, MaxZoom, MinZoom and ZoomIncrement value. 
        /// 
        /// Value to validate. 
        /// True if the value is valid, false otherwise.
        private static bool ZoomValidateValue(object o)
        {
            double value = (double)o; 
            return (!Double.IsNaN(value) && !Double.IsInfinity(value) && DoubleUtil.GreaterThan(value, 0d));
        } 
 
        /// 
        /// PropertyChanged callback for a property that affects the selection or caret rendering. 
        /// 
        private static void UpdateCaretElement(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FlowDocumentPageViewer viewer = (FlowDocumentPageViewer)d; 

            if (viewer.Selection != null) 
            { 
                CaretElement caretElement = viewer.Selection.CaretElement;
                if (caretElement != null) 
                {
                    caretElement.InvalidateVisual();
                }
            } 
        }
 
        #endregion Static Methods 

        #endregion Private Methods 

        //--------------------------------------------------------------------
        //
        //  Private Properties 
        //
        //------------------------------------------------------------------- 
 
        #region Private Properties
 
        /// 
        /// Returns FindToolBar, if enabled.
        /// 
        private FindToolBar FindToolBar 
        {
            get { return (_findToolBarHost != null) ? _findToolBarHost.Child as FindToolBar : null; } 
        } 

        #endregion Private Properties 

        //--------------------------------------------------------------------
        //
        //  Private Fields 
        //
        //------------------------------------------------------------------- 
 
        #region Private Fields
 
        private Decorator _findToolBarHost;         // Host for FindToolbar
        private ContentPosition _contentPosition;   // Current position to be maintained during zooming and resizing.
        private FlowDocumentPrintingState _printingState;   // Printing state
        private IDocumentPaginatorSource _oldDocument; // IDocumentPaginatorSource representing Document. Cached separately from DocumentViewerBase 
                                                    // due to lifetime issues.
        private object _bringContentPositionIntoViewToken = new object(); // Bring content position into view user state 
 
        private const string _findToolBarHostTemplateName = "PART_FindToolBarHost"; //Name for the Find Toolbar host.
 
        #endregion Private Fields

        //-------------------------------------------------------------------
        // 
        //  IJournalState Members
        // 
        //------------------------------------------------------------------- 

        #region IJournalState Members 

        [Serializable]
        private class JournalState : CustomJournalStateInternal
        { 
            public JournalState(int contentPosition, LogicalDirection contentPositionDirection, double zoom)
            { 
                ContentPosition = contentPosition; 
                ContentPositionDirection = contentPositionDirection;
                Zoom = zoom; 
            }
            public int ContentPosition;
            public LogicalDirection ContentPositionDirection;
            public double Zoom; 
        }
 
        ///  
        /// 
        ///  
        CustomJournalStateInternal IJournalState.GetJournalState(JournalReason journalReason)
        {
            int cp = -1;
            LogicalDirection cpDirection = LogicalDirection.Forward; 
            TextPointer contentPosition = ContentPosition as TextPointer;
            if (contentPosition != null) 
            { 
                cp = contentPosition.Offset;
                cpDirection = contentPosition.LogicalDirection; 
            }
            return new JournalState(cp, cpDirection, Zoom);
        }
 
        /// 
        ///  
        ///  
        void IJournalState.RestoreJournalState(CustomJournalStateInternal state)
        { 
            JournalState viewerState = state as JournalState;
            if (state != null)
            {
                SetCurrentValueInternal(ZoomProperty, viewerState.Zoom); 
                if (viewerState.ContentPosition != -1)
                { 
                    FlowDocument document = Document as FlowDocument; 
                    if (document != null)
                    { 
                        TextContainer textContainer = document.StructuralCache.TextContainer;
                        if (viewerState.ContentPosition <= textContainer.SymbolCount)
                        {
                            TextPointer contentPosition = textContainer.CreatePointerAtOffset(viewerState.ContentPosition, viewerState.ContentPositionDirection); 
                            // This need be called because the UI may not be ready when Contentposition is set.
                            Dispatcher.BeginInvoke(DispatcherPriority.Input, new DispatcherOperationCallback(BringContentPositionIntoView), contentPosition); 
                        } 
                    }
                } 
            }
        }

        #endregion IJournalState Members 

        //-------------------------------------------------------------------- 
        // 
        //  DTypeThemeStyleKey
        // 
        //-------------------------------------------------------------------

        #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.
//
// File: FlowDocumentPageViewer.cs 
//
// Description: FlowDocumentPageViewer provides a simple user experience for viewing 
//              one page of content at a time. The experience is optimized for 
//              FlowDocument scenarios, however any IDocumentPaginatorSource
//              can be viewed using this control. 
//
//---------------------------------------------------------------------------

using System.Collections.ObjectModel;       // ReadOnlyCollection 
using System.Printing;                      // WritingCompletedEventArgs
using System.Windows.Automation.Peers;      // AutomationPeer 
using System.Windows.Documents;             // IDocumentPaginatorSouce, ... 
using System.Windows.Documents.Serialization;  // WritingCompletedEventArgs
using System.Windows.Input;                 // UICommand 
using System.Windows.Media;                 // VisualTreeHelper
using System.Windows.Controls.Primitives;   // DocumentViewerBase, DocumentPageView
using System.Windows.Xps;                   // XpsDocumentWriter
using System.Windows.Threading; 
using MS.Internal;                          // Invariant, DoubleUtil
using MS.Internal.Commands;                 // CommandHelpers 
using MS.Internal.Documents;                // FindToolBar 
using MS.Internal.KnownBoxes;               // BooleanBoxes
using MS.Internal.PresentationFramework;    // SecurityHelper 
using MS.Internal.AppModel;                 // IJournalState
using System.Security;                      // SecurityCritical, SecurityTreatAsSafe

namespace System.Windows.Controls 
{
    ///  
    /// FlowDocumentPageViewer provides a simple user experience for viewing one page 
    /// of content at a time. The experience is optimized for FlowDocument scenarios,
    /// however any IDocumentPaginatorSource can be viewed using this control. 
    /// 
    [TemplatePart(Name = "PART_FindToolBarHost", Type = typeof(Decorator))]
    public class FlowDocumentPageViewer : DocumentViewerBase, IJournalState
    { 
        //-------------------------------------------------------------------
        // 
        //  Constructors 
        //
        //------------------------------------------------------------------- 

        #region Constructors

        ///  
        /// Initializes class-wide settings.
        ///  
        static FlowDocumentPageViewer() 
        {
            DefaultStyleKeyProperty.OverrideMetadata( 
                typeof(FlowDocumentPageViewer),
                new FrameworkPropertyMetadata(new ComponentResourceKey(typeof(PresentationUIStyleResources), "PUIFlowDocumentPageViewer")));

            _dType = DependencyObjectType.FromSystemTypeInternal(typeof(FlowDocumentPageViewer)); 

            TextBoxBase.SelectionBrushProperty.OverrideMetadata(typeof(FlowDocumentPageViewer), 
                new FrameworkPropertyMetadata(new PropertyChangedCallback(UpdateCaretElement))); 
            TextBoxBase.SelectionOpacityProperty.OverrideMetadata(typeof(FlowDocumentPageViewer),
                new FrameworkPropertyMetadata(new PropertyChangedCallback(UpdateCaretElement))); 

            // Create our CommandBindings
            CreateCommandBindings();
 
            EventManager.RegisterClassHandler(typeof(FlowDocumentPageViewer), Keyboard.KeyDownEvent, new KeyEventHandler(KeyDownHandler), true);
        } 
 
        /// 
        /// Instantiates a new instance of a FlowDocumentPageViewer. 
        /// 
        public FlowDocumentPageViewer()
            : base()
        { 
            this.LayoutUpdated += new EventHandler(HandleLayoutUpdated);
        } 
 
        #endregion Constructors
 
        //--------------------------------------------------------------------
        //
        //  Public Methods
        // 
        //-------------------------------------------------------------------
 
        #region Public Methods 

        ///  
        /// Called when the Template's tree has been generated
        /// 
        /// Whether Visuals were added to the tree.
        public override void OnApplyTemplate() 
        {
            base.OnApplyTemplate(); 
 
            // Initialize FindTooBar host.
            // If old FindToolBar is enabled, disable it first to ensure appropriate cleanup. 
            if (FindToolBar != null)
            {
                ToggleFindToolBar(false);
            } 
            _findToolBarHost = GetTemplateChild(_findToolBarHostTemplateName) as Decorator;
        } 
 
        /// 
        /// Increases the current zoom. 
        /// 
        public void IncreaseZoom()
        {
            OnIncreaseZoomCommand(); 
        }
 
        ///  
        /// Decreases the current zoom.
        ///  
        public void DecreaseZoom()
        {
            OnDecreaseZoomCommand();
        } 

        ///  
        /// Invokes the Find Toolbar. This is analogous to the ApplicationCommands.Find. 
        /// 
        public void Find() 
        {
            OnFindCommand();
        }
 
        #endregion Public Methods
 
        //-------------------------------------------------------------------- 
        //
        //  Public Properties 
        //
        //--------------------------------------------------------------------

        #region Public Properties 

        ///  
        /// Text Selection (readonly) 
        /// 
        public TextSelection Selection 
        {
            get
            {
                ITextSelection textSelection = null; 
                FlowDocument flowDocument = Document as FlowDocument;
                if (flowDocument != null) 
                { 
                    textSelection = flowDocument.StructuralCache.TextContainer.TextSelection;
                } 
                return textSelection as TextSelection;
            }
        }
 
        /// 
        /// The Zoom applied to all pages; this value is 100-based. 
        ///  
        public double Zoom
        { 
            get { return (double) GetValue(ZoomProperty); }
            set { SetValue(ZoomProperty, value); }
        }
 
        /// 
        /// The maximum allowed value of the Zoom property. 
        ///  
        public double MaxZoom
        { 
            get { return (double) GetValue(MaxZoomProperty); }
            set { SetValue(MaxZoomProperty, value); }
        }
 
        /// 
        /// The minimum allowed value of the Zoom property. 
        ///  
        public double MinZoom
        { 
            get { return (double) GetValue(MinZoomProperty); }
            set { SetValue(MinZoomProperty, value); }
        }
 
        /// 
        /// The amount the Zoom property is incremented or decremented when 
        /// the IncreaseZoom or DecreaseZoom command is executed. 
        /// 
        public double ZoomIncrement 
        {
            get { return (double) GetValue(ZoomIncrementProperty); }
            set { SetValue(ZoomIncrementProperty, value); }
        } 

        ///  
        /// Whether the viewer can increase the current zoom. 
        /// 
        public virtual bool CanIncreaseZoom 
        {
            get { return (bool) GetValue(CanIncreaseZoomProperty); }
        }
 
        /// 
        /// Whether the viewer can decrease the current zoom. 
        ///  
        public virtual bool CanDecreaseZoom
        { 
            get { return (bool) GetValue(CanDecreaseZoomProperty); }
        }

        ///  
        /// 
        ///  
        public Brush SelectionBrush 
        {
            get { return (Brush)GetValue(SelectionBrushProperty); } 
            set { SetValue(SelectionBrushProperty, value); }
        }

        ///  
        /// 
        ///  
        public double SelectionOpacity 
        {
            get { return (double)GetValue(SelectionOpacityProperty); } 
            set { SetValue(SelectionOpacityProperty, value); }
        }

        #region Public Dynamic Properties 

        ///  
        ///  
        /// 
        public static readonly DependencyProperty ZoomProperty = 
                DependencyProperty.Register(
                        "Zoom",
                        typeof(double),
                        typeof(FlowDocumentPageViewer), 
                        new FrameworkPropertyMetadata(
                                100d, 
                                new PropertyChangedCallback(ZoomChanged), 
                                new CoerceValueCallback(CoerceZoom)),
                        new ValidateValueCallback(ZoomValidateValue)); 

        /// 
        /// 
        ///  
        public static readonly DependencyProperty MaxZoomProperty =
                DependencyProperty.Register( 
                        "MaxZoom", 
                        typeof(double),
                        typeof(FlowDocumentPageViewer), 
                        new FrameworkPropertyMetadata(
                                200d,
                                new PropertyChangedCallback(MaxZoomChanged),
                                new CoerceValueCallback(CoerceMaxZoom)), 
                        new ValidateValueCallback(ZoomValidateValue));
 
        ///  
        /// 
        ///  
        public static readonly DependencyProperty MinZoomProperty =
                DependencyProperty.Register(
                        "MinZoom",
                        typeof(double), 
                        typeof(FlowDocumentPageViewer),
                        new FrameworkPropertyMetadata( 
                                80d, 
                                new PropertyChangedCallback(MinZoomChanged)),
                        new ValidateValueCallback(ZoomValidateValue)); 

        /// 
        /// 
        ///  
        public static readonly DependencyProperty ZoomIncrementProperty =
                DependencyProperty.Register( 
                        "ZoomIncrement", 
                        typeof(double),
                        typeof(FlowDocumentPageViewer), 
                        new FrameworkPropertyMetadata(10d),
                        new ValidateValueCallback(ZoomValidateValue));

        ///  
        /// 
        ///  
        protected static readonly DependencyPropertyKey CanIncreaseZoomPropertyKey = 
                DependencyProperty.RegisterReadOnly(
                        "CanIncreaseZoom", 
                        typeof(bool),
                        typeof(FlowDocumentPageViewer),
                        new FrameworkPropertyMetadata(true));
 
        /// 
        ///  
        ///  
        public static readonly DependencyProperty CanIncreaseZoomProperty = CanIncreaseZoomPropertyKey.DependencyProperty;
 
        /// 
        /// 
        /// 
        protected static readonly DependencyPropertyKey CanDecreaseZoomPropertyKey = 
                DependencyProperty.RegisterReadOnly(
                        "CanDecreaseZoom", 
                        typeof(bool), 
                        typeof(FlowDocumentPageViewer),
                        new FrameworkPropertyMetadata(true)); 

        /// 
        /// 
        ///  
        public static readonly DependencyProperty CanDecreaseZoomProperty =
                CanDecreaseZoomPropertyKey.DependencyProperty; 
 
        /// 
        ///  
        /// 
        public static readonly DependencyProperty SelectionBrushProperty =
            TextBoxBase.SelectionBrushProperty.AddOwner(typeof(FlowDocumentPageViewer));
 
        /// 
        ///  
        ///  
        public static readonly DependencyProperty SelectionOpacityProperty =
            TextBoxBase.SelectionOpacityProperty.AddOwner(typeof(FlowDocumentPageViewer)); 


        #endregion Public Dynamic Properties
 
        #endregion Public Properties
 
        //------------------------------------------------------------------- 
        //
        //  Protected Methods 
        //
        //--------------------------------------------------------------------

        #region Protected Methods 

        ///  
        /// Creates AutomationPeer () 
        /// 
        protected override AutomationPeer OnCreateAutomationPeer() 
        {
            return new FlowDocumentPageViewerAutomationPeer(this);
        }
 
        /// 
        /// This is the method that responds to the KeyDown event. 
        ///  
        /// Event arguments
        ///  
        /// Critical: get_SearchUp is defined in a non-APTCA assembly.
        /// TreatAsSafe: call to get_SearchUp does not entail any risk.
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        protected override void OnKeyDown(KeyEventArgs e)
        { 
            // Esc -- Close FindToolBar 
            if (e.Key == Key.Escape)
            { 
                if (FindToolBar != null)
                {
                    ToggleFindToolBar(false);
                    e.Handled = true; 
                }
            } 
 
            // F3 -- Invoke Find
            if (e.Key == Key.F3) 
            {
                if (CanShowFindToolBar)
                {
                    if (FindToolBar != null) 
                    {
                        // If the Shift key is also pressed, then search up. 
                        FindToolBar.SearchUp = ((e.KeyboardDevice.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift); 
                        OnFindInvoked(this, EventArgs.Empty);
                    } 
                    else
                    {
                        // Make the FindToolbar visible
                        ToggleFindToolBar(true); 
                    }
                    e.Handled = true; 
                } 
            }
 
            // If not handled, do default handling.
            if (!e.Handled)
            {
                base.OnKeyDown(e); 
            }
        } 
 
        /// 
        /// An event reporting a mouse wheel rotation. 
        /// 
        protected override void OnMouseWheel(MouseWheelEventArgs e)
        {
            // [Mouse Wheel + Control] - zooming 
            // [Mouse Wheel] - page navigation
            if (e.Delta != 0) 
            { 
                if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
                { 
                    if (e.Delta > 0)
                    {
                        IncreaseZoom();
                    } 
                    else
                    { 
                        DecreaseZoom(); 
                    }
                } 
                else
                {
                    if (e.Delta > 0)
                    { 
                        PreviousPage();
                    } 
                    else 
                    {
                        NextPage(); 
                    }
                }
                e.Handled = false;
            } 

            // If not handled, do default handling. 
            if (!e.Handled) 
            {
                base.OnMouseWheel(e); 
            }
        }

        ///  
        /// Called when ContextMenuOpening is raised on this element.
        ///  
        /// Event arguments 
        protected override void OnContextMenuOpening(ContextMenuEventArgs e)
        { 
            base.OnContextMenuOpening(e);
            DocumentViewerHelper.OnContextMenuOpening(Document as FlowDocument, this, e);
        }
 
        /// 
        /// Called when the PageViews collection is modified; this occurs when GetPageViewsCollection 
        /// returns True or if the control's template is modified. 
        /// 
        protected override void OnPageViewsChanged() 
        {
            // Change of DocumentPageView collection resets current ContentPosition.
            // This position is updated when layout process is done.
            _contentPosition = null; 

            // Apply zoom value to new DocumentPageViews 
            ApplyZoom(); 

            base.OnPageViewsChanged(); 
        }

        /// 
        /// Called when the Document property is changed. 
        /// 
        protected override void OnDocumentChanged() 
        { 
            // Document change resets current ContentPosition.
            _contentPosition = null; 

            // _oldDocument is cached from previous document changed notification.
            if (_oldDocument != null)
            { 
                DynamicDocumentPaginator dynamicDocumentPaginator = _oldDocument.DocumentPaginator as DynamicDocumentPaginator;
                if (dynamicDocumentPaginator != null) 
                { 
                    dynamicDocumentPaginator.GetPageNumberCompleted -= new GetPageNumberCompletedEventHandler(HandleGetPageNumberCompleted);
                } 

                FlowDocumentPaginator flowDocumentPaginator = _oldDocument.DocumentPaginator as FlowDocumentPaginator;
                if (flowDocumentPaginator != null)
                { 
                    flowDocumentPaginator.BreakRecordTableInvalidated -= new BreakRecordTableInvalidatedEventHandler(HandleAllBreakRecordsInvalidated);
                } 
            } 

            base.OnDocumentChanged(); 
            _oldDocument = Document;

            // Validate the new document type
            if (Document != null && !(Document is FlowDocument)) 
            {
                // Undo new document assignment. 
                Document = null; 
                // Throw exception.
                throw new NotSupportedException(SR.Get(SRID.FlowDocumentPageViewerOnlySupportsFlowDocument)); 
            }

            if(Document != null)
            { 
                DynamicDocumentPaginator dynamicDocumentPaginator = Document.DocumentPaginator as DynamicDocumentPaginator;
                if (dynamicDocumentPaginator != null) 
                { 
                    dynamicDocumentPaginator.GetPageNumberCompleted += new GetPageNumberCompletedEventHandler(HandleGetPageNumberCompleted);
                } 

                FlowDocumentPaginator flowDocumentPaginator = Document.DocumentPaginator as FlowDocumentPaginator;
                if (flowDocumentPaginator != null)
                { 
                    flowDocumentPaginator.BreakRecordTableInvalidated += new BreakRecordTableInvalidatedEventHandler(HandleAllBreakRecordsInvalidated);
                } 
            } 

            // Update the toolbar with our current document state. 
            if (!CanShowFindToolBar)
            {
                // Disable FindToolBar, if the content does not support it.
                if (FindToolBar != null) 
                {
                    ToggleFindToolBar(false); 
                } 
            }
 
            // Go to the first page of new content.
            OnGoToPageCommand(1);
        }
 
        /// 
        /// Called when print has been completed. 
        ///  
        protected virtual void OnPrintCompleted()
        { 
            ClearPrintingState();
        }

        ///  
        /// Handler for the PreviousPage command.
        ///  
        protected override void OnPreviousPageCommand() 
        {
            if (this.CanGoToPreviousPage) 
            {
                // Page navigation resets current ContentPosition.
                // This position is updated when layout process is done.
                _contentPosition = null; 

                base.OnPreviousPageCommand(); 
            } 
        }
 
        /// 
        /// Handler for the NextPage command.
        /// 
        protected override void OnNextPageCommand() 
        {
            if (this.CanGoToNextPage) 
            { 
                // Page navigation resets current ContentPosition.
                // This position is updated when layout process is done. 
                _contentPosition = null;

                base.OnNextPageCommand();
            } 
        }
 
        ///  
        /// Handler for the FirstPage command.
        ///  
        protected override void OnFirstPageCommand()
        {
            if (this.CanGoToPreviousPage)
            { 
                // Page navigation resets current ContentPosition.
                // This position is updated when layout process is done. 
                _contentPosition = null; 

                base.OnFirstPageCommand(); 
            }
        }

        ///  
        /// Handler for the LastPage command.
        ///  
        protected override void OnLastPageCommand() 
        {
            if (this.CanGoToNextPage) 
            {
                // Page navigation resets current ContentPosition.
                // This position is updated when layout process is done.
                _contentPosition = null; 

                base.OnLastPageCommand(); 
            } 
        }
 
        /// 
        /// Handler for the GoToPage command.
        /// 
        protected override void OnGoToPageCommand(int pageNumber) 
        {
            if (CanGoToPage(pageNumber) && this.MasterPageNumber != pageNumber) 
            { 
                // Page navigation resets current ContentPosition.
                // This position is updated when layout process is done. 
                _contentPosition = null;

                base.OnGoToPageCommand(pageNumber);
            } 
        }
 
        ///  
        /// Handler for the Find command.
        ///  
        protected virtual void OnFindCommand()
        {
            if (CanShowFindToolBar)
            { 
                // Toggle on the FindToolBar between visible and hidden state.
                ToggleFindToolBar(FindToolBar == null); 
            } 
        }
 
        /// 
        /// Handler for the Print command.
        /// 
        protected override void OnPrintCommand() 
        {
#if !DONOTREFPRINTINGASMMETA 
            XpsDocumentWriter docWriter; 
            PrintDocumentImageableArea ia = null;
            FlowDocumentPaginator paginator; 
            FlowDocument document = Document as FlowDocument;
            Thickness pagePadding;

            // Only one printing job is allowed. 
            if (_printingState != null)
            { 
                return; 
            }
 
            // If the document is FlowDocument, do custom printing. Otherwise go through default path.
            if (document != null)
            {
                // Show print dialog. 
                docWriter = PrintQueue.CreateXpsDocumentWriter(ref ia);
                if (docWriter != null && ia != null) 
                { 
                    // Store the current state of the document in the PrintingState
                    paginator = ((IDocumentPaginatorSource)document).DocumentPaginator as FlowDocumentPaginator; 
                    _printingState = new FlowDocumentPrintingState();
                    _printingState.XpsDocumentWriter = docWriter;
                    _printingState.PageSize = paginator.PageSize;
                    _printingState.PagePadding = document.PagePadding; 
                    _printingState.IsSelectionEnabled = IsSelectionEnabled;
 
                    // Since _printingState value is used to determine CanExecute state, we must invalidate that state. 
                    CommandManager.InvalidateRequerySuggested();
 
                    // Register for XpsDocumentWriter events.
                    docWriter.WritingCompleted += new WritingCompletedEventHandler(HandlePrintCompleted);
                    docWriter.WritingCancelled += new WritingCancelledEventHandler(HandlePrintCancelled);
 
                    // Add PreviewCanExecute handler to have a chance to disable UI Commands during printing.
                    CommandManager.AddPreviewCanExecuteHandler(this, new CanExecuteRoutedEventHandler(PreviewCanExecuteRoutedEventHandler)); 
 
                    // Suspend layout on DocumentPageViews.
                    ReadOnlyCollection pageViews = PageViews; 
                    for (int index = 0; index < pageViews.Count; index++)
                    {
                        pageViews[index].SuspendLayout();
                    } 

                    // Disable TextSelection, if currently enabled. 
                    if (IsSelectionEnabled) 
                    {
                        IsSelectionEnabled = false; 
                    }

                    // Change the PageSize and PagePadding for the document to match the CanvasSize for the printer device.
                    paginator.PageSize = new Size(ia.MediaSizeWidth, ia.MediaSizeHeight); 
                    pagePadding = document.ComputePageMargin();
                    document.PagePadding = new Thickness( 
                        Math.Max(ia.OriginWidth, pagePadding.Left), 
                        Math.Max(ia.OriginHeight, pagePadding.Top),
                        Math.Max(ia.MediaSizeWidth - (ia.OriginWidth + ia.ExtentWidth), pagePadding.Right), 
                        Math.Max(ia.MediaSizeHeight - (ia.OriginHeight + ia.ExtentHeight), pagePadding.Bottom));

                    // Send DocumentPaginator to the printer.
                    docWriter.WriteAsync(paginator); 
                }
            } 
            else 
            {
                base.OnPrintCommand(); 
            }
#endif // DONOTREFPRINTINGASMMETA
        }
 
        /// 
        /// Handler for the CancelPrint command. 
        ///  
        protected override void OnCancelPrintCommand()
        { 
#if !DONOTREFPRINTINGASMMETA
            if (_printingState != null)
            {
                _printingState.XpsDocumentWriter.CancelAsync(); 
            }
            else 
            { 
                base.OnCancelPrintCommand();
            } 
#endif // DONOTREFPRINTINGASMMETA
        }

        ///  
        /// Handler for the IncreaseZoom command.
        ///  
        protected virtual void OnIncreaseZoomCommand() 
        {
            // If can zoom in, increase zoom by the zoom increment value. 
            if (this.CanIncreaseZoom)
            {
                SetCurrentValueInternal(ZoomProperty, Math.Min(Zoom + ZoomIncrement, MaxZoom));
            } 
        }
 
        ///  
        /// Handler for the DecreaseZoom command.
        ///  
        protected virtual void OnDecreaseZoomCommand()
        {
            // If can zoom out, decrease zoom by the zoom increment value.
            if (this.CanDecreaseZoom) 
            {
                SetCurrentValueInternal(ZoomProperty, Math.Max(Zoom - ZoomIncrement, MinZoom)); 
            } 
        }
 
        #endregion Protected Methods

        //-------------------------------------------------------------------
        // 
        //  Internal Methods
        // 
        //------------------------------------------------------------------- 

        #region Internal Methods 

        /// 
        /// Allows FrameworkElement to augment the EventRoute.
        ///  
        internal override bool BuildRouteCore(EventRoute route, RoutedEventArgs args)
        { 
            // If FlowDocumentPageViewer is used as embedded viewer (in FlowDocumentReader), 
            // it is not part of logical tree, so default logic in FE to re-add logical
            // tree from branched node does not work here. 
            // But before FlowDocumentPageViewer is added to the event route, logical
            // ancestors up to Document need to be added to the route. Otherwise
            // content will not have a chance to react to events first.
            // This breaks navigation cursor management logic, because TextEditor attached 
            // to FlowDocumentPageViewer handles those events first.
            DependencyObject document = this.Document as DependencyObject; 
            if (document != null && LogicalTreeHelper.GetParent(document) != this) 
            {
                DependencyObject branchNode = route.PeekBranchNode() as DependencyObject; 
                if (branchNode != null && DocumentViewerHelper.IsLogicalDescendent(branchNode, document))
                {
                    // Add intermediate ContentElements to the route.
                    FrameworkElement.AddIntermediateElementsToRoute( 
                        LogicalTreeHelper.GetParent(document), route, args, LogicalTreeHelper.GetParent(branchNode));
                } 
            } 
            return base.BuildRouteCore(route, args);
        } 

        /// 
        /// Brings specified point into view.
        ///  
        /// Point in the viewer's coordinate system.
        /// Whether operation is pending or not. 
        ///  
        /// It is guaranteed that Point is not over any existing pages.
        ///  
        internal bool BringPointIntoView(Point point)
        {
            int index;
            Rect[] pageRects; 
            Rect pageRect;
            ReadOnlyCollection pageViews = this.PageViews; 
            bool bringIntoViewPending = false; 

            if (pageViews.Count > 0) 
            {
                // Calculate rectangles for all pages.
                pageRects = new Rect[pageViews.Count];
                for (index = 0; index < pageViews.Count; index++) 
                {
                    pageRect = new Rect(pageViews[index].RenderSize); 
                    pageRect = pageViews[index].TransformToAncestor(this).TransformBounds(pageRect); 
                    pageRects[index] = pageRect;
                } 

                // Try to find exact hit
                for (index = 0; index < pageRects.Length; index++)
                { 
                    if (pageRects[index].Contains(point))
                    { 
                        break; 
                    }
                } 

                if (index >= pageRects.Length)
                {
                    // Union all rects. 
                    pageRect = pageRects[0];
                    for (index = 1; index < pageRects.Length; index++) 
                    { 
                        pageRect.Union(pageRects[index]);
                    } 
                    //
                    if (DoubleUtil.LessThan(point.X, pageRect.Left))
                    {
                        if (this.CanGoToPreviousPage) 
                        {
                            OnPreviousPageCommand(); 
                            bringIntoViewPending = true; 
                        }
                    } 
                    else if (DoubleUtil.GreaterThan(point.X, pageRect.Right))
                    {
                        if (this.CanGoToNextPage)
                        { 
                            OnNextPageCommand();
                            bringIntoViewPending = true; 
                        } 
                    }
                    else if (DoubleUtil.LessThan(point.Y, pageRect.Top)) 
                    {
                        if (this.CanGoToPreviousPage)
                        {
                            OnPreviousPageCommand(); 
                            bringIntoViewPending = true;
                        } 
                    } 
                    else if (DoubleUtil.GreaterThan(point.Y, pageRect.Bottom))
                    { 
                        if (this.CanGoToNextPage)
                        {
                            OnNextPageCommand();
                            bringIntoViewPending = true; 
                        }
                    } 
                } 
            }
 
            return bringIntoViewPending;
        }

        ///  
        /// Bring specified content position into view.
        ///  
        internal object BringContentPositionIntoView(object arg) 
        {
            PrivateBringContentPositionIntoView(arg, false); 

            return null;
        }
 
        #endregion Internal Methods
 
        //------------------------------------------------------------------- 
        //
        //  Internal Properties 
        //
        //--------------------------------------------------------------------

        #region Internal Properties 

        ///  
        /// ContentPosition representing currently viewed content. 
        /// 
        internal ContentPosition ContentPosition 
        {
            get { return _contentPosition; }
        }
 
        /// 
        /// Whether FindToolBar can be enabled. 
        ///  
        internal bool CanShowFindToolBar
        { 
            get { return (_findToolBarHost != null && this.Document != null && this.TextEditor != null); }
        }

        ///  
        /// Whether currently printing the content.
        ///  
        internal bool IsPrinting 
        {
            get { return (_printingState != null); } 
        }

        #endregion Internal Properties
 
        //-------------------------------------------------------------------
        // 
        //  Private Methods 
        //
        //-------------------------------------------------------------------- 

        #region Private Methods

        ///  
        /// Handler for LayoutUpdated event raised by the LayoutSystem.
        ///  
        private void HandleLayoutUpdated(object sender, EventArgs e) 
        {
            DocumentPageView masterPageView; 
            DynamicDocumentPaginator documentPaginator;

            // Ignore LayoutUpdated during printing.
            if (this.Document != null && _printingState == null) 
            {
                documentPaginator = this.Document.DocumentPaginator as DynamicDocumentPaginator; 
                if (documentPaginator != null) 
                {
                    // Update ContentPosition, if not cached. 
                    if (_contentPosition == null)
                    {
                        masterPageView = GetMasterPageView();
                        if (masterPageView != null && masterPageView.DocumentPage != null) 
                        {
                            _contentPosition = documentPaginator.GetPagePosition(masterPageView.DocumentPage); 
                        } 
                        if (_contentPosition == ContentPosition.Missing)
                        { 
                            _contentPosition = null;
                        }
                    }
                    // Otherwise bring this position into view. 
                    else
                    { 
                        PrivateBringContentPositionIntoView(_contentPosition, true); 
                    }
                } 
            }
        }

        ///  
        /// Handler for GetPageNumberCompleted event raised by the Document.
        ///  
        private void HandleGetPageNumberCompleted(object sender, GetPageNumberCompletedEventArgs e) 
        {
            if (Document != null && sender == Document.DocumentPaginator && e != null) 
            {
                if (!e.Cancelled && e.Error == null && e.UserState == _bringContentPositionIntoViewToken)
                {
                    int newMasterPageNumber = e.PageNumber + 1; 

                    OnGoToPageCommand(newMasterPageNumber); 
                } 
            }
        } 

        /// 
        /// Handler for BreakRecordTableInvalidated event raised by the Paginator.
        ///  
        private void HandleAllBreakRecordsInvalidated(object sender, EventArgs e)
        { 
            ReadOnlyCollection pageViews = PageViews; 
            for (int index = 0; index < pageViews.Count; index++)
            { 
                pageViews[index].DuplicateVisual();
            }
        }
 
        /// 
        /// Handle the case when the position is no longer valid for the current document, conservatively returns true if 
        /// is uknown. 
        /// 
        private bool IsValidContentPositionForDocument(IDocumentPaginatorSource document, ContentPosition contentPosition) 
        {
            FlowDocument flowDocument = document as FlowDocument;
            TextPointer textPointer = contentPosition as TextPointer;
 
            if(flowDocument != null && textPointer != null)
            { 
                return flowDocument.ContentStart.TextContainer == textPointer.TextContainer; 
            }
 
            return true;
        }

        ///  
        /// Bring specified content position into view. (If async, cancel any previous async request to bring into view.)
        ///  
        private void PrivateBringContentPositionIntoView(object arg, bool isAsyncRequest) 
        {
            ContentPosition contentPosition = arg as ContentPosition; 
            if (contentPosition != null && Document != null)
            {
                DynamicDocumentPaginator documentPaginator = this.Document.DocumentPaginator as DynamicDocumentPaginator;
                if (documentPaginator != null && IsValidContentPositionForDocument(Document, contentPosition)) 
                {
                    documentPaginator.CancelAsync(_bringContentPositionIntoViewToken); 
 
                    if(isAsyncRequest)
                    { 
                        documentPaginator.GetPageNumberAsync(contentPosition, _bringContentPositionIntoViewToken);
                    }
                    else
                    { 
                        int newMasterPageNumber = documentPaginator.GetPageNumber(contentPosition) + 1;
 
                        OnGoToPageCommand(newMasterPageNumber); 
                    }
 
                    _contentPosition = contentPosition;
                }
            }
        } 

        ///  
        /// Called when WritingCompleted event raised by a DocumentWriter (during printing). 
        /// 
        /// Sender of the event. 
        /// Event arguments.
        private void HandlePrintCompleted(object sender, WritingCompletedEventArgs e)
        {
            OnPrintCompleted(); 
        }
 
        ///  
        /// Called when WritingCancelled event raised by a DocumentWriter (during printing).
        ///  
        /// Sender of the event.
        /// Event arguments.
        private void HandlePrintCancelled(object sender, WritingCancelledEventArgs e)
        { 
            ClearPrintingState();
        } 
 
        /// 
        /// Clears printing state. 
        /// 
        private void ClearPrintingState()
        {
#if !DONOTREFPRINTINGASMMETA 
            if (_printingState != null)
            { 
                // Resume layout on DocumentPageViews. 
                ReadOnlyCollection pageViews = PageViews;
                for (int index = 0; index < pageViews.Count; index++) 
                {
                    pageViews[index].ResumeLayout();
                }
 
                // Enable TextSelection, if it was previously enabled.
                if (_printingState.IsSelectionEnabled) 
                { 
                    IsSelectionEnabled = true;
                } 

                // Remove PreviewCanExecute handler (added when Print command was executed).
                CommandManager.RemovePreviewCanExecuteHandler(this, new CanExecuteRoutedEventHandler(PreviewCanExecuteRoutedEventHandler));
 
                // Unregister for XpsDocumentWriter events.
                _printingState.XpsDocumentWriter.WritingCompleted -= new WritingCompletedEventHandler(HandlePrintCompleted); 
                _printingState.XpsDocumentWriter.WritingCancelled -= new WritingCancelledEventHandler(HandlePrintCancelled); 

                // Restore old page metrics on FlowDocument. 
                ((FlowDocument)Document).PagePadding = _printingState.PagePadding;
                Document.DocumentPaginator.PageSize = _printingState.PageSize;

                _printingState = null; 
                // Since _documentWriter value is used to determine CanExecute state, we must invalidate that state.
                CommandManager.InvalidateRequerySuggested(); 
            } 
#endif // DONOTREFPRINTINGASMMETA
        } 

        /// 
        /// Apply zoom value to all existing DocumentPageViews.
        ///  
        private void ApplyZoom()
        { 
            int index; 
            ReadOnlyCollection pageViews;
 
            // Apply zoom value to all DocumentPageViews.
            pageViews = this.PageViews;
            for (index = 0; index < pageViews.Count; index++)
            { 
                pageViews[index].SetPageZoom(Zoom / 100.0);
            } 
        } 

        ///  
        /// Enables/disables the FindToolbar.
        /// 
        /// Whether to enable/disable FindToolBar.
        private void ToggleFindToolBar(bool enable) 
        {
            Invariant.Assert(enable == (FindToolBar == null)); 
            DocumentViewerHelper.ToggleFindToolBar(_findToolBarHost, new EventHandler(OnFindInvoked), enable); 
        }
 
        /// 
        /// Invoked when the "Find" button in the Find Toolbar is clicked.
        /// This method invokes the actual Find process.
        ///  
        /// The object that sent this event
        /// The Click Events associated with this event 
        private void OnFindInvoked(object sender, EventArgs e) 
        {
            ITextRange findResult; 
            int newMasterPageNumber;
            FindToolBar findToolBar = FindToolBar;

            if (findToolBar != null && this.TextEditor != null) 
            {
                // In order to show current text selection TextEditor requires Focus to be set on the UIScope. 
                // If there embedded controls, it may happen that embedded control currently has focus and find 
                // was invoked through hotkeys. To support this case we manually move focus to the appropriate element.
                Focus(); 

                findResult = Find(findToolBar);

                // If we found something, bring it into the view. Otherwise alert the user. 
                if ((findResult != null) && (!findResult.IsEmpty))
                { 
                    if (findResult.Start is ContentPosition) 
                    {
                        // Bring find result into view. Set also _contentPosition to the beginning of the 
                        // result, so it is visible during resizing.
                        _contentPosition = (ContentPosition)findResult.Start;
                        newMasterPageNumber = ((DynamicDocumentPaginator)this.Document.DocumentPaginator).GetPageNumber(_contentPosition) + 1;
                        OnBringIntoView(this, Rect.Empty, newMasterPageNumber); 
                    }
                } 
                else 
                {
                    DocumentViewerHelper.ShowFindUnsuccessfulMessage(findToolBar); 
                }
            }
        }
 
        /// 
        /// The Zoom has changed and needs to be updated. 
        ///  
        private void ZoomChanged(double oldValue, double newValue)
        { 
            if (!DoubleUtil.AreClose(oldValue, newValue))
            {
                UpdateCanIncreaseZoom();
                UpdateCanDecreaseZoom(); 

                // Changes to Zoom may potentially cause content reflowing. 
                // In such case Paginator will notify DocumentViewerBase 
                // about content changes through PagesChanged event and viewer
                // will invalidate appropriate properties. 
                // Hence there is no need to invalidate any properties on
                // DocumentViewerBase right now.
                ApplyZoom();
            } 
        }
 
        ///  
        /// Update CanIncreaseZoom property.
        ///  
        private void UpdateCanIncreaseZoom()
        {
            SetValue(CanIncreaseZoomPropertyKey, BooleanBoxes.Box(DoubleUtil.GreaterThan(MaxZoom, Zoom)));
        } 

        ///  
        /// Update CanDecreaseZoom property. 
        /// 
        private void UpdateCanDecreaseZoom() 
        {
            SetValue(CanDecreaseZoomPropertyKey, BooleanBoxes.Box(DoubleUtil.LessThan(MinZoom, Zoom)));
        }
 
        /// 
        /// The MaxZoom has changed and needs to be updated. 
        ///  
        private void MaxZoomChanged(double oldValue, double newValue)
        { 
            CoerceValue(ZoomProperty);
            UpdateCanIncreaseZoom();
        }
 
        /// 
        /// The MinZoom has changed and needs to be updated. 
        ///  
        private void MinZoomChanged(double oldValue, double newValue)
        { 
            CoerceValue(MaxZoomProperty);
            CoerceValue(ZoomProperty);
            UpdateCanIncreaseZoom();
            UpdateCanDecreaseZoom(); 
        }
 
        #region Commands 

        ///  
        /// Set up Command and RoutedCommand bindings.
        /// 
        private static void CreateCommandBindings()
        { 
            ExecutedRoutedEventHandler executedHandler;
            CanExecuteRoutedEventHandler canExecuteHandler; 
 
            // Create our generic ExecutedRoutedEventHandler.
            executedHandler = new ExecutedRoutedEventHandler(ExecutedRoutedEventHandler); 
            // Create our generic CanExecuteRoutedEventHandler
            canExecuteHandler = new CanExecuteRoutedEventHandler(CanExecuteRoutedEventHandler);

            // Command: ApplicationCommands.Find 
            CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentPageViewer), ApplicationCommands.Find,
                executedHandler, canExecuteHandler); 
 
            // Command: NavigationCommands.IncreaseZoom
            CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentPageViewer), NavigationCommands.IncreaseZoom, 
                executedHandler, canExecuteHandler, new KeyGesture(Key.OemPlus, ModifierKeys.Control));

            // Command: NavigationCommands.DecreaseZoom
            CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentPageViewer), NavigationCommands.DecreaseZoom, 
                executedHandler, canExecuteHandler, new KeyGesture(Key.OemMinus, ModifierKeys.Control));
 
            // Register input bindings 
            CommandManager.RegisterClassInputBinding(typeof(FlowDocumentPageViewer), new InputBinding(NavigationCommands.PreviousPage, new KeyGesture(Key.Left)));
            CommandManager.RegisterClassInputBinding(typeof(FlowDocumentPageViewer), new InputBinding(NavigationCommands.PreviousPage, new KeyGesture(Key.Up))); 
            CommandManager.RegisterClassInputBinding(typeof(FlowDocumentPageViewer), new InputBinding(NavigationCommands.PreviousPage, new KeyGesture(Key.PageUp)));
            CommandManager.RegisterClassInputBinding(typeof(FlowDocumentPageViewer), new InputBinding(NavigationCommands.NextPage, new KeyGesture(Key.Right)));
            CommandManager.RegisterClassInputBinding(typeof(FlowDocumentPageViewer), new InputBinding(NavigationCommands.NextPage, new KeyGesture(Key.Down)));
            CommandManager.RegisterClassInputBinding(typeof(FlowDocumentPageViewer), new InputBinding(NavigationCommands.NextPage, new KeyGesture(Key.PageDown))); 
            CommandManager.RegisterClassInputBinding(typeof(FlowDocumentPageViewer), new InputBinding(NavigationCommands.FirstPage, new KeyGesture(Key.Home)));
            CommandManager.RegisterClassInputBinding(typeof(FlowDocumentPageViewer), new InputBinding(NavigationCommands.FirstPage, new KeyGesture(Key.Home, ModifierKeys.Control))); 
            CommandManager.RegisterClassInputBinding(typeof(FlowDocumentPageViewer), new InputBinding(NavigationCommands.LastPage, new KeyGesture(Key.End))); 
            CommandManager.RegisterClassInputBinding(typeof(FlowDocumentPageViewer), new InputBinding(NavigationCommands.LastPage, new KeyGesture(Key.End, ModifierKeys.Control)));
        } 

        /// 
        /// Central handler for CanExecuteRouted events fired by Commands directed at FlowDocumentPageViewer.
        ///  
        /// The target of this Command, expected to be FlowDocumentPageViewer
        /// The event arguments for this event. 
        private static void CanExecuteRoutedEventHandler(object target, CanExecuteRoutedEventArgs args) 
        {
            FlowDocumentPageViewer fdpv = target as FlowDocumentPageViewer; 
            Invariant.Assert(fdpv != null, "Target of QueryEnabledEvent must be FlowDocumentPageViewer.");
            Invariant.Assert(args != null, "args cannot be null.");

            // DocumentViewerBase is capable of execution of the majority of its commands. 
            // Special rules:
            // a) Find command is enabled when Document is attached and printing is not in progress. 
            if (args.Command == ApplicationCommands.Find) 
            {
                args.CanExecute = fdpv.CanShowFindToolBar; 
            }
            else
            {
                args.CanExecute = true; 
            }
        } 
 
        /// 
        /// Central handler for all ExecutedRouted events fired by Commands directed at FlowDocumentPageViewer. 
        /// 
        /// The target of this Command, expected to be FlowDocumentPageViewer.
        /// The event arguments associated with this event.
        private static void ExecutedRoutedEventHandler(object target, ExecutedRoutedEventArgs args) 
        {
            FlowDocumentPageViewer fdpv = target as FlowDocumentPageViewer; 
            Invariant.Assert(fdpv != null, "Target of ExecuteEvent must be FlowDocumentPageViewer."); 
            Invariant.Assert(args != null, "args cannot be null.");
 
            // Now we execute the method corresponding to the Command that fired this event;
            // each Command has its own protected virtual method that performs the operation
            // corresponding to the Command.
            if (args.Command == NavigationCommands.IncreaseZoom) 
            {
                fdpv.OnIncreaseZoomCommand(); 
            } 
            else if (args.Command == NavigationCommands.DecreaseZoom)
            { 
                fdpv.OnDecreaseZoomCommand();
            }
            else if (args.Command == ApplicationCommands.Find)
            { 
                fdpv.OnFindCommand();
            } 
            else 
            {
                Invariant.Assert(false, "Command not handled in ExecutedRoutedEventHandler."); 
            }
        }

        ///  
        /// Disable commands on DocumentViewerBase when this printing is in progress.
        ///  
        private void PreviewCanExecuteRoutedEventHandler(object target, CanExecuteRoutedEventArgs args) 
        {
            FlowDocumentPageViewer fdpv = target as FlowDocumentPageViewer; 
            Invariant.Assert(fdpv != null, "Target of PreviewCanExecuteRoutedEventHandler must be FlowDocumentPageViewer.");
            Invariant.Assert(args != null, "args cannot be null.");

            // Disable UI commands, if printing is in progress. 
            if (fdpv._printingState != null)
            { 
                if (args.Command != ApplicationCommands.CancelPrint) 
                {
                    args.CanExecute = false; 
                    args.Handled = true;
                }
            }
        } 

        ///  
        /// Called when a key event occurs. 
        /// 
        private static void KeyDownHandler(object sender, KeyEventArgs e) 
        {
            DocumentViewerHelper.KeyDownHelper(e, ((FlowDocumentPageViewer)sender)._findToolBarHost);
        }
 
        #endregion Commands
 
        #region Static Methods 

        ///  
        /// Coerce the value for Zoom property.
        /// 
        private static object CoerceZoom(DependencyObject d, object value)
        { 
            Invariant.Assert(d != null && d is FlowDocumentPageViewer);
 
            double maxZoom, minZoom; 
            FlowDocumentPageViewer v = (FlowDocumentPageViewer) d;
            double zoom = (double)value; 

            maxZoom = v.MaxZoom;
            if (DoubleUtil.LessThan(maxZoom, zoom))
            { 
                return maxZoom;
            } 
 
            minZoom = v.MinZoom;
            if (DoubleUtil.GreaterThan(minZoom, zoom)) 
            {
                return minZoom;
            }
 
            return value;
        } 
 
        /// 
        /// Coerce the value for MaxZoom property. 
        /// 
        private static object CoerceMaxZoom(DependencyObject d, object value)
        {
            Invariant.Assert(d != null && d is FlowDocumentPageViewer); 

            FlowDocumentPageViewer v = (FlowDocumentPageViewer) d; 
            double minZoom = v.MinZoom; 
            if (DoubleUtil.LessThan((double)value, minZoom))
            { 
                return minZoom;
            }
            return value;
        } 

        ///  
        /// The Zoom has changed and needs to be updated. 
        /// 
        private static void ZoomChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            Invariant.Assert(d != null && d is FlowDocumentPageViewer);
            ((FlowDocumentPageViewer)d).ZoomChanged((double) e.OldValue, (double) e.NewValue);
        } 

        ///  
        /// The MaxZoom has changed and needs to be updated. 
        /// 
        private static void MaxZoomChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            Invariant.Assert(d != null && d is FlowDocumentPageViewer);
            ((FlowDocumentPageViewer)d).MaxZoomChanged((double) e.OldValue, (double) e.NewValue);
        } 

        ///  
        /// The MinZoom has changed and needs to be updated. 
        /// 
        private static void MinZoomChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            Invariant.Assert(d != null && d is FlowDocumentPageViewer);
            ((FlowDocumentPageViewer)d).MinZoomChanged((double) e.OldValue, (double) e.NewValue);
        } 

        ///  
        /// Validate Zoom, MaxZoom, MinZoom and ZoomIncrement value. 
        /// 
        /// Value to validate. 
        /// True if the value is valid, false otherwise.
        private static bool ZoomValidateValue(object o)
        {
            double value = (double)o; 
            return (!Double.IsNaN(value) && !Double.IsInfinity(value) && DoubleUtil.GreaterThan(value, 0d));
        } 
 
        /// 
        /// PropertyChanged callback for a property that affects the selection or caret rendering. 
        /// 
        private static void UpdateCaretElement(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FlowDocumentPageViewer viewer = (FlowDocumentPageViewer)d; 

            if (viewer.Selection != null) 
            { 
                CaretElement caretElement = viewer.Selection.CaretElement;
                if (caretElement != null) 
                {
                    caretElement.InvalidateVisual();
                }
            } 
        }
 
        #endregion Static Methods 

        #endregion Private Methods 

        //--------------------------------------------------------------------
        //
        //  Private Properties 
        //
        //------------------------------------------------------------------- 
 
        #region Private Properties
 
        /// 
        /// Returns FindToolBar, if enabled.
        /// 
        private FindToolBar FindToolBar 
        {
            get { return (_findToolBarHost != null) ? _findToolBarHost.Child as FindToolBar : null; } 
        } 

        #endregion Private Properties 

        //--------------------------------------------------------------------
        //
        //  Private Fields 
        //
        //------------------------------------------------------------------- 
 
        #region Private Fields
 
        private Decorator _findToolBarHost;         // Host for FindToolbar
        private ContentPosition _contentPosition;   // Current position to be maintained during zooming and resizing.
        private FlowDocumentPrintingState _printingState;   // Printing state
        private IDocumentPaginatorSource _oldDocument; // IDocumentPaginatorSource representing Document. Cached separately from DocumentViewerBase 
                                                    // due to lifetime issues.
        private object _bringContentPositionIntoViewToken = new object(); // Bring content position into view user state 
 
        private const string _findToolBarHostTemplateName = "PART_FindToolBarHost"; //Name for the Find Toolbar host.
 
        #endregion Private Fields

        //-------------------------------------------------------------------
        // 
        //  IJournalState Members
        // 
        //------------------------------------------------------------------- 

        #region IJournalState Members 

        [Serializable]
        private class JournalState : CustomJournalStateInternal
        { 
            public JournalState(int contentPosition, LogicalDirection contentPositionDirection, double zoom)
            { 
                ContentPosition = contentPosition; 
                ContentPositionDirection = contentPositionDirection;
                Zoom = zoom; 
            }
            public int ContentPosition;
            public LogicalDirection ContentPositionDirection;
            public double Zoom; 
        }
 
        ///  
        /// 
        ///  
        CustomJournalStateInternal IJournalState.GetJournalState(JournalReason journalReason)
        {
            int cp = -1;
            LogicalDirection cpDirection = LogicalDirection.Forward; 
            TextPointer contentPosition = ContentPosition as TextPointer;
            if (contentPosition != null) 
            { 
                cp = contentPosition.Offset;
                cpDirection = contentPosition.LogicalDirection; 
            }
            return new JournalState(cp, cpDirection, Zoom);
        }
 
        /// 
        ///  
        ///  
        void IJournalState.RestoreJournalState(CustomJournalStateInternal state)
        { 
            JournalState viewerState = state as JournalState;
            if (state != null)
            {
                SetCurrentValueInternal(ZoomProperty, viewerState.Zoom); 
                if (viewerState.ContentPosition != -1)
                { 
                    FlowDocument document = Document as FlowDocument; 
                    if (document != null)
                    { 
                        TextContainer textContainer = document.StructuralCache.TextContainer;
                        if (viewerState.ContentPosition <= textContainer.SymbolCount)
                        {
                            TextPointer contentPosition = textContainer.CreatePointerAtOffset(viewerState.ContentPosition, viewerState.ContentPositionDirection); 
                            // This need be called because the UI may not be ready when Contentposition is set.
                            Dispatcher.BeginInvoke(DispatcherPriority.Input, new DispatcherOperationCallback(BringContentPositionIntoView), contentPosition); 
                        } 
                    }
                } 
            }
        }

        #endregion IJournalState Members 

        //-------------------------------------------------------------------- 
        // 
        //  DTypeThemeStyleKey
        // 
        //-------------------------------------------------------------------

        #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