FlowDocumentReader.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / Framework / System / Windows / Controls / FlowDocumentReader.cs / 1 / FlowDocumentReader.cs

                            //---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
//--------------------------------------------------------------------------- 

using System;                               // Object 
using System.Collections;                   // IEnumerator 
using System.Collections.ObjectModel;       // ReadOnlyCollection
using System.Security;                      // SecurityCritical 
using System.Windows.Automation.Peers;      // AutomationPeer
using System.Windows.Data;                  // BindingOperations
using System.Windows.Controls.Primitives;   // PlacementMode
using System.Windows.Documents;             // FlowDocument 
using System.Windows.Input;                 // KeyEventArgs
using System.Windows.Media;                 // ScaleTransform, VisualTreeHelper 
using System.Windows.Markup;                // IAddChild 
using System.Windows.Threading;             // Dispatcher
using MS.Internal;                          // Invariant, DoubleUtil 
using MS.Internal.Commands;                 // CommandHelpers
using MS.Internal.Controls;                 // EmptyEnumerator
using MS.Internal.Documents;                // FindToolBar
using MS.Internal.KnownBoxes;               // BooleanBoxes 
using MS.Internal.AppModel;                 // IJournalState
 
namespace System.Windows.Controls 
{
    ///  
    /// FlowDocumentReader provides a full user experience for consuming text content.
    /// It will be used as the default viewer for loose XAML or containers that contain
    /// text content, and can be styled and re-used by developers for use within their applications.
    ///  
    [TemplatePart(Name = "PART_ContentHost", Type = typeof(Decorator))]
    [TemplatePart(Name = "PART_FindToolBarHost", Type = typeof(Decorator))] 
    [ContentProperty("Document")] 
    public class FlowDocumentReader : Control, IAddChild, IJournalState
    { 
        //-------------------------------------------------------------------
        //
        //  Constructors
        // 
        //-------------------------------------------------------------------
 
        #region Constructors 

        ///  
        /// Static Constructor
        /// 
        static FlowDocumentReader()
        { 
            DefaultStyleKeyProperty.OverrideMetadata(
                typeof(FlowDocumentReader), 
                new FrameworkPropertyMetadata(new ComponentResourceKey(typeof(PresentationUIStyleResources), "PUIFlowDocumentReader"))); 

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

            CreateCommandBindings();

            EventManager.RegisterClassHandler(typeof(FlowDocumentReader), Keyboard.KeyDownEvent, new KeyEventHandler(KeyDownHandler), true); 
        }
 
        ///  
        /// Default Constructor
        ///  
        public FlowDocumentReader()
            : base()
        {
        } 

        #endregion Constructors 
 
        //--------------------------------------------------------------------
        // 
        //  Public Methods
        //
        //-------------------------------------------------------------------
 
        #region Public Methods
 
        ///  
        /// Build Visual tree
        ///  
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
 
            // Initialize ContentHost.
            // If old ContentHost is enabled, disable it first to ensure appropriate cleanup. 
            if (CurrentViewer != null) 
            {
                DetachViewer(CurrentViewer); 
                _contentHost.Child = null;
            }
            _contentHost = GetTemplateChild(_contentHostTemplateName) as Decorator;
            if (_contentHost != null) 
            {
                if (_contentHost.Child != null) 
                { 
                    throw new NotSupportedException(SR.Get(SRID.FlowDocumentReaderDecoratorMarkedAsContentHostMustHaveNoContent));
                } 

                SwitchViewingModeCore(ViewingMode);
            }
 
            // 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;
            _findButton = GetTemplateChild(_findButtonTemplateName) as ToggleButton;
        } 

        ///  
        /// Whether the master page can be moved to the specified page. 
        /// 
        /// Page number. 
        public bool CanGoToPage(int pageNumber)
        {
            bool canGoToPage = false;
            if (CurrentViewer != null) 
            {
                canGoToPage = CurrentViewer.CanGoToPage(pageNumber); 
            } 
            return canGoToPage;
        } 

        /// 
        /// Invokes the Find Toolbar. This is analogous to the ApplicationCommands.Find.
        ///  
        public void Find()
        { 
            OnFindCommand(); 
        }
 
        /// 
        /// Invokes the Print Dialog. This is analogous to the ApplicationCommands.Print.
        /// 
        public void Print() 
        {
            OnPrintCommand(); 
        } 

        ///  
        /// Cancels current printing job. This is analogous to the ApplicationCommands.CancelPrint.
        /// 
        public void CancelPrint()
        { 
            OnCancelPrintCommand();
        } 
 
        /// 
        /// Increases the current zoom. 
        /// 
        public void IncreaseZoom()
        {
            OnIncreaseZoomCommand(); 
        }
 
        ///  
        /// Decreases the current zoom.
        ///  
        public void DecreaseZoom()
        {
            OnDecreaseZoomCommand();
        } 

        ///  
        /// Switches the current viewing mode. This is analogous to the SwitchViewingModeCommand. 
        /// 
        /// Viewing mode. 
        public void SwitchViewingMode(FlowDocumentReaderViewingMode viewingMode)
        {
            OnSwitchViewingModeCommand(viewingMode);
        } 

        #endregion Public Methods 
 
        //--------------------------------------------------------------------
        // 
        //  Public Properties
        //
        //--------------------------------------------------------------------
 
        #region Public Properties
 
        ///  
        /// ViewingMode of FlowDocumentReader.
        ///  
        public FlowDocumentReaderViewingMode ViewingMode
        {
            get { return (FlowDocumentReaderViewingMode)GetValue(ViewingModeProperty); }
            set { SetValue(ViewingModeProperty, value); } 
        }
 
        ///  
        /// Text Selection (readonly)
        ///  
        public TextSelection Selection
        {
            get
            { 
                TextSelection result = null;
                IFlowDocumentViewer viewer; 
                if (_contentHost != null) 
                {
                    viewer = _contentHost.Child as IFlowDocumentViewer; 
                    if(viewer != null)
                    {
                        result = viewer.TextSelection as TextSelection;
                    } 
                }
                return result; 
            } 
        }
 
        /// 
        /// Whether Page view can be enabled or not.
        /// 
        public bool IsPageViewEnabled 
        {
            get { return (bool)GetValue(IsPageViewEnabledProperty); } 
            set { SetValue(IsPageViewEnabledProperty, BooleanBoxes.Box(value)); } 
        }
 
        /// 
        /// Whether TwoPage view can be enabled or not.
        /// 
        public bool IsTwoPageViewEnabled 
        {
            get { return (bool)GetValue(IsTwoPageViewEnabledProperty); } 
            set { SetValue(IsTwoPageViewEnabledProperty, BooleanBoxes.Box(value)); } 
        }
 
        /// 
        /// Whether Scroll view can be enabled or not.
        /// 
        public bool IsScrollViewEnabled 
        {
            get { return (bool)GetValue(IsScrollViewEnabledProperty); } 
            set { SetValue(IsScrollViewEnabledProperty, BooleanBoxes.Box(value)); } 
        }
 
        /// 
        /// The number of pages currently available for viewing. This value
        /// is updated as content is paginated, and will change dramatically
        /// when the content is resized, or edited. 
        /// 
        public int PageCount 
        { 
            get { return (int)GetValue(PageCountProperty); }
        } 

        /// 
        /// The one-based page number of the page being displayed. If there is no content,
        /// this value will be 0. 
        /// 
        public int PageNumber 
        { 
            get { return (int)GetValue(PageNumberProperty); }
        } 

        /// 
        /// Whether the viewer can move the master page to the previous page.
        ///  
        public bool CanGoToPreviousPage
        { 
            get { return (bool)GetValue(CanGoToPreviousPageProperty); } 
        }
 
        /// 
        /// Whether the viewer can advance the master page to the next page.
        /// 
        public bool CanGoToNextPage 
        {
            get { return (bool)GetValue(CanGoToNextPageProperty); } 
        } 

        ///  
        /// Is find function enabled or not
        /// 
        public bool IsFindEnabled
        { 
            get { return (bool)GetValue(IsFindEnabledProperty); }
            set { SetValue(IsFindEnabledProperty, BooleanBoxes.Box(value)); } 
        } 

        ///  
        /// Is print function enabled or not
        /// 
        public bool IsPrintEnabled
        { 
            get { return (bool)GetValue(IsPrintEnabledProperty); }
            set { SetValue(IsPrintEnabledProperty, BooleanBoxes.Box(value)); } 
        } 

        ///  
        /// A Property representing a content of this FlowDocumentScrollViewer.
        /// 
        public FlowDocument Document
        { 
            get { return (FlowDocument)GetValue(DocumentProperty); }
            set { SetValue(DocumentProperty, value); } 
        } 

        ///  
        /// 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 bool CanIncreaseZoom 
        {
            get { return (bool)GetValue(CanIncreaseZoomProperty); } 
        } 

        ///  
        /// Whether the viewer can decrease the current zoom.
        /// 
        public bool CanDecreaseZoom
        { 
            get { return (bool)GetValue(CanDecreaseZoomProperty); }
        } 
 
        #region Public Dynamic Properties
 
        /// 
        /// 
        /// 
        public static readonly DependencyProperty ViewingModeProperty = 
                DependencyProperty.Register(
                        "ViewingMode", 
                        typeof(FlowDocumentReaderViewingMode), 
                        typeof(FlowDocumentReader),
                        new FrameworkPropertyMetadata( 
                                FlowDocumentReaderViewingMode.Page,
                                FrameworkPropertyMetadataOptions.AffectsMeasure,
                                new PropertyChangedCallback(ViewingModeChanged)),
                        new ValidateValueCallback(IsValidViewingMode)); 

        ///  
        ///  
        /// 
        public static readonly DependencyProperty IsPageViewEnabledProperty = 
                DependencyProperty.Register(
                        "IsPageViewEnabled",
                        typeof(bool),
                        typeof(FlowDocumentReader), 
                        new FrameworkPropertyMetadata(
                                BooleanBoxes.TrueBox, 
                                new PropertyChangedCallback(ViewingModeEnabledChanged))); 

        ///  
        /// 
        /// 
        public static readonly DependencyProperty IsTwoPageViewEnabledProperty =
                DependencyProperty.Register( 
                        "IsTwoPageViewEnabled",
                        typeof(bool), 
                        typeof(FlowDocumentReader), 
                        new FrameworkPropertyMetadata(
                                BooleanBoxes.TrueBox, 
                                new PropertyChangedCallback(ViewingModeEnabledChanged)));

        /// 
        ///  
        /// 
        public static readonly DependencyProperty IsScrollViewEnabledProperty = 
                DependencyProperty.Register( 
                        "IsScrollViewEnabled",
                        typeof(bool), 
                        typeof(FlowDocumentReader),
                        new FrameworkPropertyMetadata(
                                BooleanBoxes.TrueBox,
                                new PropertyChangedCallback(ViewingModeEnabledChanged))); 

        ///  
        ///  
        /// 
        private static readonly DependencyPropertyKey PageCountPropertyKey = 
                DependencyProperty.RegisterReadOnly(
                        "PageCount",
                        typeof(int),
                        typeof(FlowDocumentReader), 
                        new FrameworkPropertyMetadata(0));
 
        ///  
        /// 
        ///  
        public static readonly DependencyProperty PageCountProperty = PageCountPropertyKey.DependencyProperty;

        /// 
        ///  
        /// 
        private static readonly DependencyPropertyKey PageNumberPropertyKey = 
                DependencyProperty.RegisterReadOnly( 
                        "PageNumber",
                        typeof(int), 
                        typeof(FlowDocumentReader),
                        new FrameworkPropertyMetadata(0));

        ///  
        /// 
        ///  
        public static readonly DependencyProperty PageNumberProperty = PageNumberPropertyKey.DependencyProperty; 
        /// 
        ///  
        /// 
        private static readonly DependencyPropertyKey CanGoToPreviousPagePropertyKey =
                DependencyProperty.RegisterReadOnly(
                        "CanGoToPreviousPage", 
                        typeof(bool),
                        typeof(FlowDocumentReader), 
                        new FrameworkPropertyMetadata(BooleanBoxes.FalseBox)); 

        ///  
        /// 
        /// 
        public static readonly DependencyProperty CanGoToPreviousPageProperty = CanGoToPreviousPagePropertyKey.DependencyProperty;
 
        /// 
        ///  
        ///  
        private static readonly DependencyPropertyKey CanGoToNextPagePropertyKey =
                DependencyProperty.RegisterReadOnly( 
                        "CanGoToNextPage",
                        typeof(bool),
                        typeof(FlowDocumentReader),
                        new FrameworkPropertyMetadata(BooleanBoxes.FalseBox)); 

        ///  
        ///  
        /// 
        public static readonly DependencyProperty CanGoToNextPageProperty = CanGoToNextPagePropertyKey.DependencyProperty; 

        /// 
        /// 
        ///  
        public static readonly DependencyProperty IsFindEnabledProperty =
                DependencyProperty.Register( 
                        "IsFindEnabled", 
                        typeof(bool),
                        typeof(FlowDocumentReader), 
                        new FrameworkPropertyMetadata(
                                BooleanBoxes.TrueBox,
                                new PropertyChangedCallback(IsFindEnabledChanged)));
 
        /// 
        ///  
        ///  
        public static readonly DependencyProperty IsPrintEnabledProperty =
                DependencyProperty.Register( 
                        "IsPrintEnabled",
                        typeof(bool),
                        typeof(FlowDocumentReader),
                        new FrameworkPropertyMetadata( 
                                BooleanBoxes.TrueBox,
                                new PropertyChangedCallback(IsPrintEnabledChanged))); 
 
        /// 
        ///  
        /// 
        public static readonly DependencyProperty DocumentProperty =
                DependencyProperty.Register(
                        "Document", 
                        typeof(FlowDocument),
                        typeof(FlowDocumentReader), 
                        new FrameworkPropertyMetadata( 
                                null,
                                new PropertyChangedCallback(DocumentChanged))); 

        /// 
        /// 
        ///  
        public static readonly DependencyProperty ZoomProperty =
                FlowDocumentPageViewer.ZoomProperty.AddOwner( 
                        typeof(FlowDocumentReader), 
                        new FrameworkPropertyMetadata(
                                100d, 
                                new PropertyChangedCallback(ZoomChanged),
                                new CoerceValueCallback(CoerceZoom)));

        ///  
        /// 
        ///  
        public static readonly DependencyProperty MaxZoomProperty = 
                FlowDocumentPageViewer.MaxZoomProperty.AddOwner(
                        typeof(FlowDocumentReader), 
                        new FrameworkPropertyMetadata(
                                200d,
                                new PropertyChangedCallback(MaxZoomChanged),
                                new CoerceValueCallback(CoerceMaxZoom))); 

        ///  
        ///  
        /// 
        public static readonly DependencyProperty MinZoomProperty = 
                FlowDocumentPageViewer.MinZoomProperty.AddOwner(
                        typeof(FlowDocumentReader),
                        new FrameworkPropertyMetadata(
                                80d, 
                                new PropertyChangedCallback(MinZoomChanged)));
 
        ///  
        /// 
        ///  
        public static readonly DependencyProperty ZoomIncrementProperty =
                FlowDocumentPageViewer.ZoomIncrementProperty.AddOwner(
                        typeof(FlowDocumentReader));
 
        /// 
        ///  
        ///  
        private static readonly DependencyPropertyKey CanIncreaseZoomPropertyKey =
                DependencyProperty.RegisterReadOnly( 
                        "CanIncreaseZoom",
                        typeof(bool),
                        typeof(FlowDocumentReader),
                        new FrameworkPropertyMetadata(BooleanBoxes.TrueBox)); 

        ///  
        ///  
        /// 
        public static readonly DependencyProperty CanIncreaseZoomProperty = CanIncreaseZoomPropertyKey.DependencyProperty; 

        /// 
        /// 
        ///  
        private static readonly DependencyPropertyKey CanDecreaseZoomPropertyKey =
                DependencyProperty.RegisterReadOnly( 
                        "CanDecreaseZoom", 
                        typeof(bool),
                        typeof(FlowDocumentReader), 
                        new FrameworkPropertyMetadata(BooleanBoxes.TrueBox));

        /// 
        ///  
        /// 
        public static readonly DependencyProperty CanDecreaseZoomProperty = CanDecreaseZoomPropertyKey.DependencyProperty; 
 
        #endregion Public Dynamic Properties
 
        #endregion Public Properties

        //-------------------------------------------------------------------
        // 
        //  Public Commands
        // 
        //-------------------------------------------------------------------- 

        #region Public Commands 

        /// 
        /// Switch ViewingMode command
        ///  
        public static readonly RoutedUICommand SwitchViewingModeCommand = new RoutedUICommand(SR.Get(SRID.SwitchViewingMode), "SwitchViewingMode", typeof(FlowDocumentReader), null);
 
        #endregion 

        //------------------------------------------------------------------- 
        //
        //  Protected Methods
        //
        //------------------------------------------------------------------- 

        #region Protected Methods 
 
        /// 
        /// Called when print has been completed. 
        /// 
        protected virtual void OnPrintCompleted()
        {
            if (_printInProgress) 
            {
                _printInProgress = false; 
                // Since _printInProgress value is used to determine CanExecute state, we must invalidate that state. 
                CommandManager.InvalidateRequerySuggested();
            } 
        }

        /// 
        /// 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 virtual void OnPrintCommand() 
        {
            if (CurrentViewer != null)
            {
                CurrentViewer.Print(); 
            }
        } 
 
        /// 
        /// Handler for the CancelPrint command. 
        /// 
        protected virtual void OnCancelPrintCommand()
        {
            if (CurrentViewer != null) 
            {
                CurrentViewer.CancelPrint(); 
            } 
        }
 
        /// 
        /// Handler for the IncreaseZoom command.
        /// 
        protected virtual void OnIncreaseZoomCommand() 
        {
            // If can zoom in, increase zoom by the zoom increment value. 
            if (CanIncreaseZoom) 
            {
                Zoom = 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 (CanDecreaseZoom)
            {
                Zoom = Math.Max(Zoom - ZoomIncrement, MinZoom);
            } 
        }
 
        ///  
        /// Handler for the SwitchViewingMode command.
        ///  
        /// Viewing mode.
        protected virtual void OnSwitchViewingModeCommand(FlowDocumentReaderViewingMode viewingMode)
        {
            SwitchViewingModeCore(viewingMode); 
        }
 
        ///  
        /// Called when IsInitialized is set to true.
        ///  
        /// Event arguments
        protected override void OnInitialized(EventArgs e)
        {
            base.OnInitialized(e); 

            // Defer the Is*ViewEnabled & ViewingMode conflict exception. 
            // Otherwise  won't work. 
            if (IsInitialized && !CanSwitchToViewingMode(ViewingMode))
            { 
                throw new ArgumentException(SR.Get(SRID.FlowDocumentReaderViewingModeEnabledConflict));
            }
        }
 
        /// 
        /// Creates AutomationPeer () 
        ///  
        protected override AutomationPeer OnCreateAutomationPeer()
        { 
            return new FlowDocumentReaderAutomationPeer(this);
        }

        ///  
        /// An event reporting that the IsKeyboardFocusWithin property changed.
        ///  
        protected override void OnIsKeyboardFocusWithinChanged(DependencyPropertyChangedEventArgs e) 
        {
            base.OnIsKeyboardFocusWithinChanged(e); 

            // In order to enable selection rendering and other similar services, the embedded viewer
            // needs to get focus, when any part of the control gets focused.
            // But if the focus is within the Document, do not change it. Otherwise it 
            // will interfere with input handling inside the Document.
            if (IsKeyboardFocusWithin && CurrentViewer != null) 
            { 
                bool isFocusWithinDocument = IsFocusWithinDocument();
                if (!isFocusWithinDocument) 
                {
                    ((FrameworkElement)CurrentViewer).Focus();
                }
            } 
        }
 
        ///  
        /// 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) 
        {
            if (e.Handled) { return; } 

            switch (e.Key)
            {
                // Esc -- Close FindToolBar 
                case Key.Escape:
                    if (FindToolBar != null) 
                    { 
                        ToggleFindToolBar(false);
                        e.Handled = true; 
                    }
                    break;

                // F3 -- Invoke Find 
                case 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;
                    }
                    break;
            } 

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

        #endregion Protected Methods 

        //------------------------------------------------------------------- 
        // 
        //  Protected Properties
        // 
        //--------------------------------------------------------------------

        #region Protected Properties
 
        /// 
        /// Returns enumerator to logical children. 
        ///  
        protected internal override IEnumerator LogicalChildren
        { 
            get
            {
                if (HasLogicalChildren && Document != null)
                { 
                    return new SingleChildEnumerator(Document);
                } 
                return EmptyEnumerator.Instance; 
            }
        } 

        #endregion Protected Properties

        //------------------------------------------------------------------- 
        //
        //  Internal Methods 
        // 
        //--------------------------------------------------------------------
 
        #region Internal Methods

        /// 
        /// Allows FrameworkElement to augment the EventRoute. 
        /// 
        internal override bool BuildRouteCore(EventRoute route, RoutedEventArgs args) 
        { 
            // Do not add intermediate ContentElements to the route,
            // because they were added by embedded viewer. 
            return BuildRouteCoreHelper(route, args, false);
        }

        #endregion Internal Methods 

        //-------------------------------------------------------------------- 
        // 
        //  Private Methods
        // 
        //-------------------------------------------------------------------

        #region Private Methods
 
        /// 
        /// Handler for the SwitchViewingMode command. 
        ///  
        /// Viewing mode.
        protected virtual void SwitchViewingModeCore(FlowDocumentReaderViewingMode viewingMode) 
        {
            ITextSelection textSelection = null;
            ContentPosition contentPosition = null;
            IFlowDocumentViewer viewer; 
            FrameworkElement feViewer;
            bool isKeyboardFocusWithin; 
            DependencyObject focusedElement = null; 

            if (_contentHost != null) 
            {
                // Remember the current keyboard focus state.
                isKeyboardFocusWithin = IsKeyboardFocusWithin;
 
                // Detach old viewer
                viewer = _contentHost.Child as IFlowDocumentViewer; 
                if (viewer != null) 
                {
                    // Remember focused element, if the focus is within the Document. 
                    // After switching to a different viewer, this focus needs to be restored.
                    if (isKeyboardFocusWithin)
                    {
                        bool isFocusWithinDocument = IsFocusWithinDocument(); 
                        if (isFocusWithinDocument)
                        { 
                            focusedElement = Keyboard.FocusedElement as DependencyObject; 
                        }
                    } 

                    // Retrieve the current viewing state from the old viewer.
                    textSelection = viewer.TextSelection;
                    contentPosition = viewer.ContentPosition; 

                    // Detach old viewer 
                    DetachViewer(viewer); 
                }
 
                viewer = GetViewerFromMode(viewingMode);
                feViewer = (FrameworkElement)viewer;
                if (viewer != null)
                { 
                    // Attach new viewer
                    _contentHost.Child = feViewer; 
                    AttachViewer(viewer); 

                    // Restore viewing state. 
                    viewer.TextSelection = textSelection;
                    viewer.ContentPosition = contentPosition;

                    // Bring the focus to previously focused element within the document 
                    // or to the current viewer.
                    if (isKeyboardFocusWithin) 
                    { 
                        if (focusedElement is UIElement)
                        { 
                            ((UIElement)focusedElement).Focus();
                        }
                        else if (focusedElement is ContentElement)
                        { 
                            ((ContentElement)focusedElement).Focus();
                        } 
                        else 
                        {
                            feViewer.Focus(); 
                        }
                    }
                }
 
                // Viewer changes invalidates following properties:
                //      - PageCount 
                //      - PageNumber 
                //      - CanGoToPreviousPage
                //      - CanGoToNextPage 
                UpdateReadOnlyProperties(true, true);
            }
        }
 
        /// 
        /// Determines whether focus is within Document. 
        ///  
        private bool IsFocusWithinDocument()
        { 
            DependencyObject focusedElement = Keyboard.FocusedElement as DependencyObject;
            while (focusedElement != null && focusedElement != Document)
            {
                // Skip elements in the control's template (if such exists) and 
                // walk up logical tree to find if the focused element is within
                // the document. 
                FrameworkElement fe = focusedElement as FrameworkElement; 
                if (fe != null && fe.TemplatedParent != null)
                { 
                    focusedElement = fe.TemplatedParent;
                }
                else
                { 
                    focusedElement = LogicalTreeHelper.GetParent(focusedElement);
                } 
            } 
            return (focusedElement != null);
        } 

        /// 
        /// The Document has changed and needs to be updated.
        ///  
        private void DocumentChanged(FlowDocument oldDocument, FlowDocument newDocument)
        { 
            // Cleanup state associated with the old document. 
            if (oldDocument != null)
            { 
                // If Document was added to logical tree before, remove it.
                if (_documentAsLogicalChild)
                {
                    RemoveLogicalChild(oldDocument); 
                }
            } 
 
            // If FlowDocumentReader was created through style, then do not modify
            // the logical tree. Instead, set "core parent" for the Document. 
            if (TemplatedParent != null && newDocument != null && LogicalTreeHelper.GetParent(newDocument) != null)
            {
                // Set the "core parent" back to us.
                ContentOperations.SetParent(newDocument, this); 
                _documentAsLogicalChild = false;
            } 
            else 
            {
                _documentAsLogicalChild = true; 
            }

            // Initialize state associated with the new document.
            if (newDocument != null) 
            {
                // If Document should be part of DocumentViewer's logical tree, add it. 
                if (_documentAsLogicalChild) 
                {
                    AddLogicalChild(newDocument); 
                }
            }

            // Attach document to the current viewer. 
            if (CurrentViewer != null)
            { 
                CurrentViewer.SetDocument(newDocument); 
            }
 
            // Document invalidation invalidates following properties:
            //      - PageCount
            //      - PageNumber
            //      - CanGoToPreviousPage 
            //      - CanGoToNextPage
            UpdateReadOnlyProperties(true, true); 
 
            // Update the toolbar with our current document state.
            if (!CanShowFindToolBar) 
            {
                // Disable FindToolBar, if the content does not support it.
                if (FindToolBar != null)
                { 
                    ToggleFindToolBar(false);
                } 
            } 

            // Document is also represented as Automation child. Need to invalidate peer to force update. 
            FlowDocumentReaderAutomationPeer peer = UIElementAutomationPeer.FromElement(this) as FlowDocumentReaderAutomationPeer;
            if (peer != null)
            {
                peer.InvalidatePeer(); 
            }
        } 
 
        /// 
        /// Detach embedded viewer form the reader control. 
        /// 
        private void DetachViewer(IFlowDocumentViewer viewer)
        {
            Invariant.Assert(viewer != null && viewer is FrameworkElement); 
            FrameworkElement feViewer = (FrameworkElement)viewer;
            // Clear property bindings. 
            BindingOperations.ClearBinding(feViewer, ZoomProperty); 
            BindingOperations.ClearBinding(feViewer, MaxZoomProperty);
            BindingOperations.ClearBinding(feViewer, MinZoomProperty); 
            BindingOperations.ClearBinding(feViewer, ZoomIncrementProperty);
            // Unregister event handlers.
            viewer.PageCountChanged -= new EventHandler(OnPageCountChanged);
            viewer.PageNumberChanged -= new EventHandler(OnPageNumberChanged); 
            viewer.PrintStarted -= new EventHandler(OnViewerPrintStarted);
            viewer.PrintCompleted -= new EventHandler(OnViewerPrintCompleted); 
            // Clear TemplatedParent 
            //feViewer._templatedParent = null;
            // Detach document 
            viewer.SetDocument(null);
        }

        ///  
        /// Attach embedded viewer to the reader control.
        ///  
        private void AttachViewer(IFlowDocumentViewer viewer) 
        {
            Invariant.Assert(viewer != null && viewer is FrameworkElement); 
            FrameworkElement feViewer = (FrameworkElement)viewer;
            // Set document
            viewer.SetDocument(Document);
            // Set TemplatedParent 
            //feViewer._templatedParent = TemplatedParent;
            // Register event handlers. 
            viewer.PageCountChanged += new EventHandler(OnPageCountChanged); 
            viewer.PageNumberChanged += new EventHandler(OnPageNumberChanged);
            viewer.PrintStarted += new EventHandler(OnViewerPrintStarted); 
            viewer.PrintCompleted += new EventHandler(OnViewerPrintCompleted);
            // Create property bindings.
            CreateTwoWayBinding(feViewer, ZoomProperty, "Zoom");
            CreateTwoWayBinding(feViewer, MaxZoomProperty, "MaxZoom"); 
            CreateTwoWayBinding(feViewer, MinZoomProperty, "MinZoom");
            CreateTwoWayBinding(feViewer, ZoomIncrementProperty, "ZoomIncrement"); 
        } 

        ///  
        /// Create two way property binding.
        /// 
        private void CreateTwoWayBinding(FrameworkElement fe, DependencyProperty dp, string propertyPath)
        { 
            Binding binding = new Binding(propertyPath);
            binding.Mode = BindingMode.TwoWay; 
            binding.Source = this; 
            fe.SetBinding(dp, binding);
        } 

        /// 
        /// Determines whether can switch to specified ViewingMode or not.
        ///  
        private bool CanSwitchToViewingMode(FlowDocumentReaderViewingMode mode)
        { 
            bool canSwitch = false; 
            switch (mode)
            { 
                case FlowDocumentReaderViewingMode.Page:
                    canSwitch = IsPageViewEnabled;
                    break;
                case FlowDocumentReaderViewingMode.TwoPage: 
                    canSwitch = IsTwoPageViewEnabled;
                    break; 
                case FlowDocumentReaderViewingMode.Scroll: 
                    canSwitch = IsScrollViewEnabled;
                    break; 
            }
            return canSwitch;
        }
 
        /// 
        /// Retrieves viewer form specified ViewingMode. 
        ///  
        private IFlowDocumentViewer GetViewerFromMode(FlowDocumentReaderViewingMode mode)
        { 
            IFlowDocumentViewer viewer = null;
            switch (mode)
            {
                case FlowDocumentReaderViewingMode.Page: 
                    if (_pageViewer == null)
                    { 
                        _pageViewer = new ReaderPageViewer(); 
                        _pageViewer.SetResourceReference(StyleProperty, PageViewStyleKey);
                        _pageViewer.Name = "PageViewer"; 
                        CommandManager.AddPreviewCanExecuteHandler(_pageViewer, new CanExecuteRoutedEventHandler(PreviewCanExecuteRoutedEventHandler));
                    }
                    viewer = _pageViewer;
                    break; 
                case FlowDocumentReaderViewingMode.TwoPage:
                    if (_twoPageViewer == null) 
                    { 
                        _twoPageViewer = new ReaderTwoPageViewer();
                        _twoPageViewer.SetResourceReference(StyleProperty, TwoPageViewStyleKey); 
                        _twoPageViewer.Name = "TwoPageViewer";
                        CommandManager.AddPreviewCanExecuteHandler(_twoPageViewer, new CanExecuteRoutedEventHandler(PreviewCanExecuteRoutedEventHandler));
                    }
                    viewer = _twoPageViewer; 
                    break;
                case FlowDocumentReaderViewingMode.Scroll: 
                    if (_scrollViewer == null) 
                    {
                        _scrollViewer = new ReaderScrollViewer(); 
                        _scrollViewer.SetResourceReference(StyleProperty, ScrollViewStyleKey);
                        _scrollViewer.Name = "ScrollViewer";
                        CommandManager.AddPreviewCanExecuteHandler(_scrollViewer, new CanExecuteRoutedEventHandler(PreviewCanExecuteRoutedEventHandler));
                    } 
                    viewer = _scrollViewer;
                    break; 
            } 
            return viewer;
        } 

        /// 
        /// Update values for readonly properties.
        ///  
        /// Whether PageCount has been changed.
        /// Whether PageNumber has been changed. 
        private void UpdateReadOnlyProperties(bool pageCountChanged, bool pageNumberChanged) 
        {
            if (pageCountChanged) 
            {
                SetValue(PageCountPropertyKey, (CurrentViewer != null) ? CurrentViewer.PageCount : 0);
            }
 
            if (pageNumberChanged)
            { 
                SetValue(PageNumberPropertyKey, (CurrentViewer != null) ? CurrentViewer.PageNumber : 0); 
                SetValue(CanGoToPreviousPagePropertyKey, (CurrentViewer != null) ? CurrentViewer.CanGoToPreviousPage : false);
            } 

            if (pageCountChanged || pageNumberChanged)
            {
                SetValue(CanGoToNextPagePropertyKey, (CurrentViewer != null) ? CurrentViewer.CanGoToNextPage : false); 
            }
        } 
 
        /// 
        /// Event handler for IFlowDocumentViewer.PageCountChanged. 
        /// 
        private void OnPageCountChanged(object sender, EventArgs e)
        {
            Invariant.Assert(CurrentViewer != null && sender == CurrentViewer); 
            UpdateReadOnlyProperties(true, false);
        } 
 
        /// 
        /// Event handler for IFlowDocumentViewer.PageNumberChanged. 
        /// 
        private void OnPageNumberChanged(object sender, EventArgs e)
        {
            Invariant.Assert(CurrentViewer != null && sender == CurrentViewer); 
            UpdateReadOnlyProperties(false, true);
        } 
 
        /// 
        /// Event handler for IFlowDocumentViewer.PrintStarted. 
        /// 
        private void OnViewerPrintStarted(object sender, EventArgs e)
        {
            Invariant.Assert(CurrentViewer != null && sender == CurrentViewer); 
            _printInProgress = true;
            // Since _printInProgress value is used to determine CanExecute state, we must invalidate that state. 
            CommandManager.InvalidateRequerySuggested(); 
        }
 
        /// 
        /// Event handler for IFlowDocumentViewer.PrintCompleted.
        /// 
        private void OnViewerPrintCompleted(object sender, EventArgs e) 
        {
            Invariant.Assert(CurrentViewer != null && sender == CurrentViewer); 
            OnPrintCompleted(); 
        }
 
        /// 
        /// Convert object value to FlowDocumentReaderViewingMode.
        /// 
        private bool ConvertToViewingMode(object value, out FlowDocumentReaderViewingMode mode) 
        {
            bool success; 
            if (value is FlowDocumentReaderViewingMode) 
            {
                mode = (FlowDocumentReaderViewingMode)value; 
                success = true;
            }
            else if (value is String)
            { 
                String str = (String)value;
                if (str == FlowDocumentReaderViewingMode.Page.ToString()) 
                { 
                    mode = FlowDocumentReaderViewingMode.Page;
                    success = true; 
                }
                else if (str == FlowDocumentReaderViewingMode.TwoPage.ToString())
                {
                    mode = FlowDocumentReaderViewingMode.TwoPage; 
                    success = true;
                } 
                else if (str == FlowDocumentReaderViewingMode.Scroll.ToString()) 
                {
                    mode = FlowDocumentReaderViewingMode.Scroll; 
                    success = true;
                }
                else
                { 
                    mode = FlowDocumentReaderViewingMode.Page;
                    success = false; 
                } 
            }
            else 
            {
                mode = FlowDocumentReaderViewingMode.Page;
                success = false;
            } 
            return success;
        } 
 
        /// 
        /// Enables/disables the FindToolBar. 
        /// 
        /// Whether to enable/disable FindToolBar.
        private void ToggleFindToolBar(bool enable)
        { 
            Invariant.Assert(enable == (FindToolBar == null));
 
            // Command event for toggle button is only fired in OnClick - Therefore we just need to change the state 
            if(_findButton != null && _findButton.IsChecked.HasValue && _findButton.IsChecked.Value != enable)
            { 
                _findButton.IsChecked = enable;
            }
            DocumentViewerHelper.ToggleFindToolBar(_findToolBarHost, new EventHandler(OnFindInvoked), enable);
        } 

        #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: SwitchViewingMode
            CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentReader), FlowDocumentReader.SwitchViewingModeCommand, 
                executedHandler, canExecuteHandler, SRID.KeySwitchViewingMode, SRID.KeySwitchViewingModeDisplayString);
 
            // Command: ApplicationCommands.Find 
            CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentReader), ApplicationCommands.Find,
                executedHandler, canExecuteHandler); 

            // Command: ApplicationCommands.Print
            CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentReader), ApplicationCommands.Print,
                executedHandler, canExecuteHandler); 

            // Command: ApplicationCommands.CancelPrint 
            CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentReader), ApplicationCommands.CancelPrint, 
                executedHandler, canExecuteHandler);
 
            // Command: NavigationCommands.PreviousPage
            CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentReader), NavigationCommands.PreviousPage,
                executedHandler, canExecuteHandler);
 
            // Command: NavigationCommands.NextPage
            CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentReader), NavigationCommands.NextPage, 
                executedHandler, canExecuteHandler); 

            // Command: NavigationCommands.FirstPage 
            CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentReader), NavigationCommands.FirstPage,
                executedHandler, canExecuteHandler);

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

            // Command: NavigationCommands.DecreaseZoom
            CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentReader), NavigationCommands.DecreaseZoom, 
                executedHandler, canExecuteHandler, new KeyGesture(Key.OemMinus, ModifierKeys.Control));
        } 
 
        /// 
        /// Central handler for CanExecute events fired by Commands directed at FlowDocumentReader. 
        /// 
        /// The target of this Command, expected to be FlowDocumentReader
        /// The event arguments for this event.
        private static void CanExecuteRoutedEventHandler(object target, CanExecuteRoutedEventArgs args) 
        {
            FlowDocumentReader viewer = target as FlowDocumentReader; 
            Invariant.Assert(viewer != null, "Target of CanExecuteRoutedEventHandler must be FlowDocumentReader."); 
            Invariant.Assert(args != null, "args cannot be null.");
 
            // FlowDocumentReader is capable of execution of the majority of its commands.
            // Special rules:
            // a) during printing only CancelPrint is enabled.
            // b) Find command is enabled only when FindToolBar is enabled. 
            // c) Print command is enabled when Document is attached and printing is enabled.
            // d) CancelPrint command is enabled only during printing. 
            // e) SwitchViewingMode command is enabled if the viewing mode is enabled, or 
            //    the command has no parameters (will switch to the next available view).
            if (!viewer._printInProgress) 
            {
                if (args.Command == FlowDocumentReader.SwitchViewingModeCommand)
                {
                    // This command is enabled if the viewing mode is enabled, or the command 
                    // has no parameters (will switch to the next available view).
                    FlowDocumentReaderViewingMode mode; 
                    if (viewer.ConvertToViewingMode(args.Parameter, out mode)) 
                    {
                        args.CanExecute = viewer.CanSwitchToViewingMode(mode); 
                    }
                    else
                    {
                        args.CanExecute = (args.Parameter == null); 
                    }
                } 
                else if (args.Command == ApplicationCommands.Find) 
                {
                    args.CanExecute = viewer.CanShowFindToolBar; 
                }
                else if (args.Command == ApplicationCommands.Print)
                {
                    args.CanExecute = (viewer.Document != null) && viewer.IsPrintEnabled; 
                }
                else if (args.Command == ApplicationCommands.CancelPrint) 
                { 
                    args.CanExecute = false;
                } 
                else
                {
                    args.CanExecute = true;
                } 
            }
            else 
            { 
                args.CanExecute = (args.Command == ApplicationCommands.CancelPrint);
            } 
        }

        /// 
        /// Central handler for all ExecuteEvents fired by Commands directed at FlowDocumentReader. 
        /// 
        /// The target of this Command, expected to be FlowDocumentReader. 
        /// The event arguments associated with this event. 
        private static void ExecutedRoutedEventHandler(object target, ExecutedRoutedEventArgs args)
        { 
            FlowDocumentReader viewer = target as FlowDocumentReader;
            Invariant.Assert(viewer != null, "Target of ExecutedRoutedEventHandler must be FlowDocumentReader.");
            Invariant.Assert(args != null, "args cannot be null.");
 
            if (args.Command == FlowDocumentReader.SwitchViewingModeCommand)
            { 
                viewer.TrySwitchViewingMode(args.Parameter); 
            }
            else if (args.Command == ApplicationCommands.Find) 
            {
                viewer.OnFindCommand();
            }
            else if (args.Command == ApplicationCommands.Print) 
            {
                viewer.OnPrintCommand(); 
            } 
            else if (args.Command == ApplicationCommands.CancelPrint)
            { 
                viewer.OnCancelPrintCommand();
            }
            else if (args.Command == NavigationCommands.IncreaseZoom)
            { 
                viewer.OnIncreaseZoomCommand();
            } 
            else if (args.Command == NavigationCommands.DecreaseZoom) 
            {
                viewer.OnDecreaseZoomCommand(); 
            }
            else if (args.Command == NavigationCommands.PreviousPage)
            {
                viewer.OnPreviousPageCommand(); 
            }
            else if (args.Command == NavigationCommands.NextPage) 
            { 
                viewer.OnNextPageCommand();
            } 
            else if (args.Command == NavigationCommands.FirstPage)
            {
                viewer.OnFirstPageCommand();
            } 
            else if (args.Command == NavigationCommands.LastPage)
            { 
                viewer.OnLastPageCommand(); 
            }
            else 
            {
                Invariant.Assert(false, "Command not handled in ExecutedRoutedEventHandler.");
            }
        } 

        ///  
        /// Changes the current viewing mode. 
        /// 
        private void TrySwitchViewingMode(object parameter) 
        {
            FlowDocumentReaderViewingMode mode;
            // Convert command parameter to viewing mode value.
            // If parameter is not provided, the viewing mode is the next one available. 
            // If parameter cannot be converted, the command is ignored.
            if (!ConvertToViewingMode(parameter, out mode)) 
            { 
                if (parameter == null)
                { 
                    mode = (FlowDocumentReaderViewingMode)((((int)ViewingMode) + 1) % 3);
                }
                else
                { 
                    return;
                } 
            } 
            // If the current ViewingMode is disabled, go to next one.
            while (!CanSwitchToViewingMode(mode)) 
            {
                mode = (FlowDocumentReaderViewingMode)((((int)mode) + 1) % 3);
            }
            // Set new ViewingMode value. 
            ViewingMode = mode;
        } 
 
        /// 
        /// Handler for the PreviousPage command. 
        /// 
        private void OnPreviousPageCommand()
        {
            if (CurrentViewer != null) 
            {
                CurrentViewer.PreviousPage(); 
            } 
        }
 
        /// 
        /// Handler for the NextPage command.
        /// 
        private void OnNextPageCommand() 
        {
            if (CurrentViewer != null) 
            { 
                CurrentViewer.NextPage();
            } 
        }

        /// 
        /// Handler for the FirstPage command. 
        /// 
        private void OnFirstPageCommand() 
        { 
            if (CurrentViewer != null)
            { 
                CurrentViewer.FirstPage();
            }
        }
 
        /// 
        /// Handler for the LastPage command. 
        ///  
        private void OnLastPageCommand()
        { 
            if (CurrentViewer != null)
            {
                CurrentViewer.LastPage();
            } 
        }
 
        ///  
        /// 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; 
            TextEditor textEditor = TextEditor; 
            FindToolBar findToolBar = FindToolBar;
 
            if (findToolBar != null && 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.
                if (CurrentViewer != null && CurrentViewer is UIElement) 
                { 
                    ((UIElement)CurrentViewer).Focus();
                } 

                findResult = DocumentViewerHelper.Find(findToolBar, textEditor, textEditor.TextView, textEditor.TextView);

                // If we found something, bring it into the view. Otherwise alert the user. 
                if ((findResult != null) && (!findResult.IsEmpty))
                { 
                    // Bring find result into view. 
                    if (CurrentViewer != null)
                    { 
                        CurrentViewer.ShowFindResult(findResult);
                    }
                }
                else 
                {
                    DocumentViewerHelper.ShowFindUnsuccessfulMessage(findToolBar); 
                } 
            }
        } 

        /// 
        /// Disable commands on IFlowDocumentViewer when this funcionality is explicitly
        /// disabled on the reader control. 
        /// 
        private void PreviewCanExecuteRoutedEventHandler(object target, CanExecuteRoutedEventArgs args) 
        { 
            if (args.Command == ApplicationCommands.Find)
            { 
                // Find is handled by FlowDocumentReader.
                args.CanExecute = false;
                args.Handled = true;
            } 
            else if (args.Command == ApplicationCommands.Print)
            { 
                args.CanExecute = IsPrintEnabled; 
                args.Handled = !IsPrintEnabled;
            } 
        }

        /// 
        /// Called when a key event occurs. 
        /// 
        private static void KeyDownHandler(object sender, KeyEventArgs e) 
        { 
            DocumentViewerHelper.KeyDownHelper(e, ((FlowDocumentReader)sender)._findToolBarHost);
        } 

        #endregion Commands

        #region Static Methods 

        ///  
        /// ViewingMode has been changed. 
        /// 
        private static void ViewingModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            Invariant.Assert(d != null && d is FlowDocumentReader);
            FlowDocumentReader viewer = (FlowDocumentReader)d;
            if (viewer.CanSwitchToViewingMode((FlowDocumentReaderViewingMode)e.NewValue)) 
            {
                viewer.SwitchViewingModeCore((FlowDocumentReaderViewingMode)e.NewValue); 
            } 
            else if (viewer.IsInitialized)
            { 
                throw new ArgumentException(SR.Get(SRID.FlowDocumentReaderViewingModeEnabledConflict));
            }

            // Fire automation events if automation is active. 
            FlowDocumentReaderAutomationPeer peer = UIElementAutomationPeer.FromElement(viewer) as FlowDocumentReaderAutomationPeer;
            if (peer != null) 
            { 
                peer.RaiseCurrentViewChangedEvent((FlowDocumentReaderViewingMode)e.NewValue, (FlowDocumentReaderViewingMode)e.OldValue);
            } 
        }

        /// 
        /// Validate value of ViewingMode property. 
        /// 
        private static bool IsValidViewingMode(object o) 
        { 
            FlowDocumentReaderViewingMode value = (FlowDocumentReaderViewingMode)o;
            return (value == FlowDocumentReaderViewingMode.Page || 
                    value == FlowDocumentReaderViewingMode.TwoPage ||
                    value == FlowDocumentReaderViewingMode.Scroll);
        }
 
        /// 
        /// One of viewing modes has been enabled/disabled. 
        ///  
        private static void ViewingModeEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        { 
            Invariant.Assert(d != null && d is FlowDocumentReader);
            FlowDocumentReader viewer = (FlowDocumentReader)d;

            // Cannot disable all viewing modes. 
            if (!viewer.IsPageViewEnabled &&
                !viewer.IsTwoPageViewEnabled && 
                !viewer.IsScrollViewEnabled) 
            {
                throw new ArgumentException(SR.Get(SRID.FlowDocumentReaderCannotDisableAllViewingModes)); 
            }

            // Cannot disable the current viewing mode.
            if (viewer.IsInitialized && !viewer.CanSwitchToViewingMode(viewer.ViewingMode)) 
            {
                throw new ArgumentException(SR.Get(SRID.FlowDocumentReaderViewingModeEnabledConflict)); 
            } 

            // Fire automation events if automation is active. 
            FlowDocumentReaderAutomationPeer peer = UIElementAutomationPeer.FromElement(viewer) as FlowDocumentReaderAutomationPeer;
            if (peer != null)
            {
                peer.RaiseSupportedViewsChangedEvent(e); 
            }
        } 
 
        /// 
        /// IsFindEnabled value has changed. 
        /// 
        private static void IsFindEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Invariant.Assert(d != null && d is FlowDocumentReader); 
            FlowDocumentReader viewer = (FlowDocumentReader)d;
 
            // Update the toolbar with our current state. 
            if (!viewer.CanShowFindToolBar)
            { 
                if (viewer.FindToolBar != null)
                {
                    viewer.ToggleFindToolBar(false);
                } 
            }
 
            // Since IsFindEnabled state is used to determine CanExecute state, we must invalidate that state. 
            CommandManager.InvalidateRequerySuggested();
        } 

        /// 
        /// IsPrintEnabled value has changed.
        ///  
        private static void IsPrintEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        { 
            Invariant.Assert(d != null && d is FlowDocumentReader); 
            FlowDocumentReader viewer = (FlowDocumentReader)d;
 
            // Since IsPrintEnabled state is used to determine CanExecute state, we must invalidate that state.
            CommandManager.InvalidateRequerySuggested();
        }
 
        /// 
        /// The Document has changed and needs to be updated. 
        ///  
        private static void DocumentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        { 
            Invariant.Assert(d != null && d is FlowDocumentReader);
            FlowDocumentReader viewer = (FlowDocumentReader)d;
            viewer.DocumentChanged((FlowDocument)e.OldValue, (FlowDocument)e.NewValue);
 
            // Since Document state is used to determine CanExecute state, we must invalidate that state.
            CommandManager.InvalidateRequerySuggested(); 
        } 

        ///  
        /// The Zoom has changed and needs to be updated.
        /// 
        private static void ZoomChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        { 
            Invariant.Assert(d != null && d is FlowDocumentReader);
            FlowDocumentReader viewer = (FlowDocumentReader)d; 
            if (!DoubleUtil.AreClose((double)e.OldValue, (double)e.NewValue)) 
            {
                // If zoom has been changed, CanIncrease/DecreaseZoom property need to be updated. 
                viewer.SetValue(CanIncreaseZoomPropertyKey, BooleanBoxes.Box(DoubleUtil.GreaterThan(viewer.MaxZoom, viewer.Zoom)));
                viewer.SetValue(CanDecreaseZoomPropertyKey, BooleanBoxes.Box(DoubleUtil.LessThan(viewer.MinZoom, viewer.Zoom)));
            }
        } 

        ///  
        /// Coerce Zoom with Max/MinZoom, MinZoom works as the baseline. 
        /// 
        private static object CoerceZoom(DependencyObject d, object value) 
        {
            Invariant.Assert(d != null && d is FlowDocumentReader);
            FlowDocumentReader viewer = (FlowDocumentReader)d;
 
            double zoom = (double)value;
 
            double maxZoom = viewer.MaxZoom; 
            if (DoubleUtil.LessThan(maxZoom, zoom))
            { 
                return maxZoom;
            }

            double minZoom = viewer.MinZoom; 
            if (DoubleUtil.GreaterThan(minZoom, zoom))
            { 
                return minZoom; 
            }
 
            return value;
        }

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

            viewer.CoerceValue(ZoomProperty);
            viewer.SetValue(CanIncreaseZoomPropertyKey, BooleanBoxes.Box(DoubleUtil.GreaterThan(viewer.MaxZoom, viewer.Zoom))); 
        }
 
        ///  
        /// MaxZoom need to be coerced if MinZoom > MaxZoom
        ///  
        private static object CoerceMaxZoom(DependencyObject d, object value)
        {
            Invariant.Assert(d != null && d is FlowDocumentReader);
            FlowDocumentReader viewer = (FlowDocumentReader)d; 

            double min = viewer.MinZoom; 
            return ((double)value < min) ? min : value; 
        }
 
        /// 
        /// The MinZoom has changed and needs to be updated.
        /// 
        private static void MinZoomChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            Invariant.Assert(d != null && d is FlowDocumentReader); 
            FlowDocumentReader viewer = (FlowDocumentReader)d; 

            viewer.CoerceValue(MaxZoomProperty); 
            viewer.CoerceValue(ZoomProperty);
            viewer.SetValue(CanDecreaseZoomPropertyKey, BooleanBoxes.Box(DoubleUtil.LessThan(viewer.MinZoom, viewer.Zoom)));
        }
 
        /// 
        /// 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)); 
        }
 
        #endregion Static Methods 

        #endregion Private Methods 

        //--------------------------------------------------------------------
        //
        //  Private Properties 
        //
        //------------------------------------------------------------------- 
 
        #region Private Properties
 
        /// 
        /// Whether FindToolBar can be enabled.
        /// 
        private bool CanShowFindToolBar 
        {
            get { return ((_findToolBarHost != null) && IsFindEnabled && (Document != null)); } 
        } 

        ///  
        /// Returns TextEditor, if availabe.
        /// 
        private TextEditor TextEditor
        { 
            get
            { 
                TextEditor textEditor = null; 
                IFlowDocumentViewer currentViewer = CurrentViewer;
                if (currentViewer != null && currentViewer.TextSelection != null) 
                {
                    textEditor = currentViewer.TextSelection.TextEditor;
                }
                return textEditor; 
            }
        } 
 
        /// 
        /// Returns FindToolBar, if enabled. 
        /// 
        private FindToolBar FindToolBar
        {
            get { return (_findToolBarHost != null) ? _findToolBarHost.Child as FindToolBar : null; } 
        }
 
        ///  
        /// Returns the current content viewer.
        ///  
        private IFlowDocumentViewer CurrentViewer
        {
            get
            { 
                if (_contentHost != null)
                { 
                    return (IFlowDocumentViewer)_contentHost.Child; 
                }
                return null; 
            }
        }

        #endregion Private Properties 

        //------------------------------------------------------------------- 
        // 
        //  Private Fields
        // 
        //-------------------------------------------------------------------

        #region Private Fields
 
        private Decorator _contentHost;                 // Host for content viewer
        private Decorator _findToolBarHost;             // Host for FindToolBar 
        private ToggleButton _findButton;               // Find toggle button 
        private ReaderPageViewer _pageViewer;           // Viewer for Page viewing mode
        private ReaderTwoPageViewer _twoPageViewer;     // Viewer for TwoPage viewing mode 
        private ReaderScrollViewer _scrollViewer;       // Viewer for Scroll viewing mode
        private bool _documentAsLogicalChild;           // Is Document part of logical tree
        private bool _printInProgress;                  // Whether print is currently in progress.
 
        private const string _contentHostTemplateName = "PART_ContentHost";         // Name for ContentHost
        private const string _findToolBarHostTemplateName = "PART_FindToolBarHost"; // Name for the Find ToolBar host 
        private const string _findButtonTemplateName = "FindButton"; // Name for the Find Button 

        #endregion Private Fields 

        //--------------------------------------------------------------------
        //
        //  IAddChild Members 
        //
        //------------------------------------------------------------------- 
 
        #region IAddChild Members
 
        /// 
        /// Called to add the object as a Child.
        /// 
        /// Object to add as a child. 
        /// FlowDocumentScrollViewer only supports a single child of type IDocumentPaginator.
        void IAddChild.AddChild(Object value) 
        { 
            if (value == null)
            { 
                throw new ArgumentNullException("value");
            }
            // Check if Content has already been set.
            if (this.Document != null) 
            {
                throw new ArgumentException(SR.Get(SRID.FlowDocumentReaderCanHaveOnlyOneChild)); 
            } 
            if (!(value is FlowDocument))
            { 
                throw new ArgumentException(SR.Get(SRID.UnexpectedParameterType, value.GetType(), typeof(FlowDocument)), "value");
            }
            Document = value as FlowDocument;
        } 

        ///  
        /// Called when text appears under the tag in markup 
        /// 
        /// Text to add to the Object. 
        /// FlowDocumentScrollViewer does not support Text children.
        void IAddChild.AddText(string text)
        {
            XamlSerializerUtil.ThrowIfNonWhiteSpaceInAddText(text, this); 
        }
 
        #endregion IAddChild Members 

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

        #region IJournalState Members 
 
        [Serializable]
        private class JournalState : CustomJournalStateInternal 
        {
            public JournalState(int contentPosition, LogicalDirection contentPositionDirection, double zoom, FlowDocumentReaderViewingMode viewingMode)
            {
                ContentPosition = contentPosition; 
                ContentPositionDirection = contentPositionDirection;
                Zoom = zoom; 
                ViewingMode = viewingMode; 
            }
            public int ContentPosition; 
            public LogicalDirection ContentPositionDirection;
            public double Zoom;
            public FlowDocumentReaderViewingMode ViewingMode;
        } 

        ///  
        ///  
        /// 
        CustomJournalStateInternal IJournalState.GetJournalState(JournalReason journalReason) 
        {
            int cp = -1;
            LogicalDirection cpDirection = LogicalDirection.Forward;
            IFlowDocumentViewer viewer = CurrentViewer; 
            if (viewer != null)
            { 
                TextPointer contentPosition = viewer.ContentPosition as TextPointer; 
                if (contentPosition != null)
                { 
                    cp = contentPosition.Offset;
                    cpDirection = contentPosition.LogicalDirection;
                }
            } 
            return new JournalState(cp, cpDirection, Zoom, ViewingMode);
        } 
 
        /// 
        ///  
        /// 
        void IJournalState.RestoreJournalState(CustomJournalStateInternal state)
        {
            JournalState viewerState = state as JournalState; 
            if (state != null)
            { 
                Zoom = viewerState.Zoom; 
                ViewingMode = viewerState.ViewingMode;
                if (viewerState.ContentPosition != -1) 
                {
                    IFlowDocumentViewer viewer = CurrentViewer;
                    FlowDocument document = Document;
                    if (viewer != null && document != null) 
                    {
                        TextContainer textContainer = document.StructuralCache.TextContainer; 
                        if (viewerState.ContentPosition <= textContainer.SymbolCount) 
                        {
                            TextPointer contentPosition = textContainer.CreatePointerAtOffset(viewerState.ContentPosition, viewerState.ContentPositionDirection); 
                            viewer.ContentPosition = 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

        //------------------------------------------------------------------- 
        //
        //  Style Keys 
        // 
        //-------------------------------------------------------------------
 
        #region Style Keys

        /// 
        /// Key used to mark the style for use by the PageView 
        /// 
        private static ResourceKey PageViewStyleKey 
        { 
            get
            { 
                if (_pageViewStyleKey == null)
                {
                    _pageViewStyleKey = new ComponentResourceKey(typeof(PresentationUIStyleResources), "PUIPageViewStyleKey");
                } 

                return _pageViewStyleKey; 
            } 
        }
 
        /// 
        /// Key used to mark the style for use by the TwoPageView
        /// 
        private static ResourceKey TwoPageViewStyleKey 
        {
            get 
            { 
                if (_twoPageViewStyleKey == null)
                { 
                    _twoPageViewStyleKey = new ComponentResourceKey(typeof(PresentationUIStyleResources), "PUITwoPageViewStyleKey");
                }

                return _twoPageViewStyleKey; 
            }
        } 
 
        /// 
        /// Key used to mark the style for use by the ScrollView 
        /// 
        private static ResourceKey ScrollViewStyleKey
        {
            get 
            {
                if (_scrollViewStyleKey == null) 
                { 
                    _scrollViewStyleKey = new ComponentResourceKey(typeof(PresentationUIStyleResources), "PUIScrollViewStyleKey");
                } 

                return _scrollViewStyleKey;
            }
        } 

 
        private static ComponentResourceKey _pageViewStyleKey; 
        private static ComponentResourceKey _twoPageViewStyleKey;
        private static ComponentResourceKey _scrollViewStyleKey; 

        #endregion
    }
 
    /// 
    /// 
 
    public enum FlowDocumentReaderViewingMode
    { 
        /// 
        ///

        Page, 

        ///  
        /// 

        TwoPage, 

        /// 
        ///
 
        Scroll
    } 
} 

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

using System;                               // Object 
using System.Collections;                   // IEnumerator 
using System.Collections.ObjectModel;       // ReadOnlyCollection
using System.Security;                      // SecurityCritical 
using System.Windows.Automation.Peers;      // AutomationPeer
using System.Windows.Data;                  // BindingOperations
using System.Windows.Controls.Primitives;   // PlacementMode
using System.Windows.Documents;             // FlowDocument 
using System.Windows.Input;                 // KeyEventArgs
using System.Windows.Media;                 // ScaleTransform, VisualTreeHelper 
using System.Windows.Markup;                // IAddChild 
using System.Windows.Threading;             // Dispatcher
using MS.Internal;                          // Invariant, DoubleUtil 
using MS.Internal.Commands;                 // CommandHelpers
using MS.Internal.Controls;                 // EmptyEnumerator
using MS.Internal.Documents;                // FindToolBar
using MS.Internal.KnownBoxes;               // BooleanBoxes 
using MS.Internal.AppModel;                 // IJournalState
 
namespace System.Windows.Controls 
{
    ///  
    /// FlowDocumentReader provides a full user experience for consuming text content.
    /// It will be used as the default viewer for loose XAML or containers that contain
    /// text content, and can be styled and re-used by developers for use within their applications.
    ///  
    [TemplatePart(Name = "PART_ContentHost", Type = typeof(Decorator))]
    [TemplatePart(Name = "PART_FindToolBarHost", Type = typeof(Decorator))] 
    [ContentProperty("Document")] 
    public class FlowDocumentReader : Control, IAddChild, IJournalState
    { 
        //-------------------------------------------------------------------
        //
        //  Constructors
        // 
        //-------------------------------------------------------------------
 
        #region Constructors 

        ///  
        /// Static Constructor
        /// 
        static FlowDocumentReader()
        { 
            DefaultStyleKeyProperty.OverrideMetadata(
                typeof(FlowDocumentReader), 
                new FrameworkPropertyMetadata(new ComponentResourceKey(typeof(PresentationUIStyleResources), "PUIFlowDocumentReader"))); 

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

            CreateCommandBindings();

            EventManager.RegisterClassHandler(typeof(FlowDocumentReader), Keyboard.KeyDownEvent, new KeyEventHandler(KeyDownHandler), true); 
        }
 
        ///  
        /// Default Constructor
        ///  
        public FlowDocumentReader()
            : base()
        {
        } 

        #endregion Constructors 
 
        //--------------------------------------------------------------------
        // 
        //  Public Methods
        //
        //-------------------------------------------------------------------
 
        #region Public Methods
 
        ///  
        /// Build Visual tree
        ///  
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
 
            // Initialize ContentHost.
            // If old ContentHost is enabled, disable it first to ensure appropriate cleanup. 
            if (CurrentViewer != null) 
            {
                DetachViewer(CurrentViewer); 
                _contentHost.Child = null;
            }
            _contentHost = GetTemplateChild(_contentHostTemplateName) as Decorator;
            if (_contentHost != null) 
            {
                if (_contentHost.Child != null) 
                { 
                    throw new NotSupportedException(SR.Get(SRID.FlowDocumentReaderDecoratorMarkedAsContentHostMustHaveNoContent));
                } 

                SwitchViewingModeCore(ViewingMode);
            }
 
            // 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;
            _findButton = GetTemplateChild(_findButtonTemplateName) as ToggleButton;
        } 

        ///  
        /// Whether the master page can be moved to the specified page. 
        /// 
        /// Page number. 
        public bool CanGoToPage(int pageNumber)
        {
            bool canGoToPage = false;
            if (CurrentViewer != null) 
            {
                canGoToPage = CurrentViewer.CanGoToPage(pageNumber); 
            } 
            return canGoToPage;
        } 

        /// 
        /// Invokes the Find Toolbar. This is analogous to the ApplicationCommands.Find.
        ///  
        public void Find()
        { 
            OnFindCommand(); 
        }
 
        /// 
        /// Invokes the Print Dialog. This is analogous to the ApplicationCommands.Print.
        /// 
        public void Print() 
        {
            OnPrintCommand(); 
        } 

        ///  
        /// Cancels current printing job. This is analogous to the ApplicationCommands.CancelPrint.
        /// 
        public void CancelPrint()
        { 
            OnCancelPrintCommand();
        } 
 
        /// 
        /// Increases the current zoom. 
        /// 
        public void IncreaseZoom()
        {
            OnIncreaseZoomCommand(); 
        }
 
        ///  
        /// Decreases the current zoom.
        ///  
        public void DecreaseZoom()
        {
            OnDecreaseZoomCommand();
        } 

        ///  
        /// Switches the current viewing mode. This is analogous to the SwitchViewingModeCommand. 
        /// 
        /// Viewing mode. 
        public void SwitchViewingMode(FlowDocumentReaderViewingMode viewingMode)
        {
            OnSwitchViewingModeCommand(viewingMode);
        } 

        #endregion Public Methods 
 
        //--------------------------------------------------------------------
        // 
        //  Public Properties
        //
        //--------------------------------------------------------------------
 
        #region Public Properties
 
        ///  
        /// ViewingMode of FlowDocumentReader.
        ///  
        public FlowDocumentReaderViewingMode ViewingMode
        {
            get { return (FlowDocumentReaderViewingMode)GetValue(ViewingModeProperty); }
            set { SetValue(ViewingModeProperty, value); } 
        }
 
        ///  
        /// Text Selection (readonly)
        ///  
        public TextSelection Selection
        {
            get
            { 
                TextSelection result = null;
                IFlowDocumentViewer viewer; 
                if (_contentHost != null) 
                {
                    viewer = _contentHost.Child as IFlowDocumentViewer; 
                    if(viewer != null)
                    {
                        result = viewer.TextSelection as TextSelection;
                    } 
                }
                return result; 
            } 
        }
 
        /// 
        /// Whether Page view can be enabled or not.
        /// 
        public bool IsPageViewEnabled 
        {
            get { return (bool)GetValue(IsPageViewEnabledProperty); } 
            set { SetValue(IsPageViewEnabledProperty, BooleanBoxes.Box(value)); } 
        }
 
        /// 
        /// Whether TwoPage view can be enabled or not.
        /// 
        public bool IsTwoPageViewEnabled 
        {
            get { return (bool)GetValue(IsTwoPageViewEnabledProperty); } 
            set { SetValue(IsTwoPageViewEnabledProperty, BooleanBoxes.Box(value)); } 
        }
 
        /// 
        /// Whether Scroll view can be enabled or not.
        /// 
        public bool IsScrollViewEnabled 
        {
            get { return (bool)GetValue(IsScrollViewEnabledProperty); } 
            set { SetValue(IsScrollViewEnabledProperty, BooleanBoxes.Box(value)); } 
        }
 
        /// 
        /// The number of pages currently available for viewing. This value
        /// is updated as content is paginated, and will change dramatically
        /// when the content is resized, or edited. 
        /// 
        public int PageCount 
        { 
            get { return (int)GetValue(PageCountProperty); }
        } 

        /// 
        /// The one-based page number of the page being displayed. If there is no content,
        /// this value will be 0. 
        /// 
        public int PageNumber 
        { 
            get { return (int)GetValue(PageNumberProperty); }
        } 

        /// 
        /// Whether the viewer can move the master page to the previous page.
        ///  
        public bool CanGoToPreviousPage
        { 
            get { return (bool)GetValue(CanGoToPreviousPageProperty); } 
        }
 
        /// 
        /// Whether the viewer can advance the master page to the next page.
        /// 
        public bool CanGoToNextPage 
        {
            get { return (bool)GetValue(CanGoToNextPageProperty); } 
        } 

        ///  
        /// Is find function enabled or not
        /// 
        public bool IsFindEnabled
        { 
            get { return (bool)GetValue(IsFindEnabledProperty); }
            set { SetValue(IsFindEnabledProperty, BooleanBoxes.Box(value)); } 
        } 

        ///  
        /// Is print function enabled or not
        /// 
        public bool IsPrintEnabled
        { 
            get { return (bool)GetValue(IsPrintEnabledProperty); }
            set { SetValue(IsPrintEnabledProperty, BooleanBoxes.Box(value)); } 
        } 

        ///  
        /// A Property representing a content of this FlowDocumentScrollViewer.
        /// 
        public FlowDocument Document
        { 
            get { return (FlowDocument)GetValue(DocumentProperty); }
            set { SetValue(DocumentProperty, value); } 
        } 

        ///  
        /// 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 bool CanIncreaseZoom 
        {
            get { return (bool)GetValue(CanIncreaseZoomProperty); } 
        } 

        ///  
        /// Whether the viewer can decrease the current zoom.
        /// 
        public bool CanDecreaseZoom
        { 
            get { return (bool)GetValue(CanDecreaseZoomProperty); }
        } 
 
        #region Public Dynamic Properties
 
        /// 
        /// 
        /// 
        public static readonly DependencyProperty ViewingModeProperty = 
                DependencyProperty.Register(
                        "ViewingMode", 
                        typeof(FlowDocumentReaderViewingMode), 
                        typeof(FlowDocumentReader),
                        new FrameworkPropertyMetadata( 
                                FlowDocumentReaderViewingMode.Page,
                                FrameworkPropertyMetadataOptions.AffectsMeasure,
                                new PropertyChangedCallback(ViewingModeChanged)),
                        new ValidateValueCallback(IsValidViewingMode)); 

        ///  
        ///  
        /// 
        public static readonly DependencyProperty IsPageViewEnabledProperty = 
                DependencyProperty.Register(
                        "IsPageViewEnabled",
                        typeof(bool),
                        typeof(FlowDocumentReader), 
                        new FrameworkPropertyMetadata(
                                BooleanBoxes.TrueBox, 
                                new PropertyChangedCallback(ViewingModeEnabledChanged))); 

        ///  
        /// 
        /// 
        public static readonly DependencyProperty IsTwoPageViewEnabledProperty =
                DependencyProperty.Register( 
                        "IsTwoPageViewEnabled",
                        typeof(bool), 
                        typeof(FlowDocumentReader), 
                        new FrameworkPropertyMetadata(
                                BooleanBoxes.TrueBox, 
                                new PropertyChangedCallback(ViewingModeEnabledChanged)));

        /// 
        ///  
        /// 
        public static readonly DependencyProperty IsScrollViewEnabledProperty = 
                DependencyProperty.Register( 
                        "IsScrollViewEnabled",
                        typeof(bool), 
                        typeof(FlowDocumentReader),
                        new FrameworkPropertyMetadata(
                                BooleanBoxes.TrueBox,
                                new PropertyChangedCallback(ViewingModeEnabledChanged))); 

        ///  
        ///  
        /// 
        private static readonly DependencyPropertyKey PageCountPropertyKey = 
                DependencyProperty.RegisterReadOnly(
                        "PageCount",
                        typeof(int),
                        typeof(FlowDocumentReader), 
                        new FrameworkPropertyMetadata(0));
 
        ///  
        /// 
        ///  
        public static readonly DependencyProperty PageCountProperty = PageCountPropertyKey.DependencyProperty;

        /// 
        ///  
        /// 
        private static readonly DependencyPropertyKey PageNumberPropertyKey = 
                DependencyProperty.RegisterReadOnly( 
                        "PageNumber",
                        typeof(int), 
                        typeof(FlowDocumentReader),
                        new FrameworkPropertyMetadata(0));

        ///  
        /// 
        ///  
        public static readonly DependencyProperty PageNumberProperty = PageNumberPropertyKey.DependencyProperty; 
        /// 
        ///  
        /// 
        private static readonly DependencyPropertyKey CanGoToPreviousPagePropertyKey =
                DependencyProperty.RegisterReadOnly(
                        "CanGoToPreviousPage", 
                        typeof(bool),
                        typeof(FlowDocumentReader), 
                        new FrameworkPropertyMetadata(BooleanBoxes.FalseBox)); 

        ///  
        /// 
        /// 
        public static readonly DependencyProperty CanGoToPreviousPageProperty = CanGoToPreviousPagePropertyKey.DependencyProperty;
 
        /// 
        ///  
        ///  
        private static readonly DependencyPropertyKey CanGoToNextPagePropertyKey =
                DependencyProperty.RegisterReadOnly( 
                        "CanGoToNextPage",
                        typeof(bool),
                        typeof(FlowDocumentReader),
                        new FrameworkPropertyMetadata(BooleanBoxes.FalseBox)); 

        ///  
        ///  
        /// 
        public static readonly DependencyProperty CanGoToNextPageProperty = CanGoToNextPagePropertyKey.DependencyProperty; 

        /// 
        /// 
        ///  
        public static readonly DependencyProperty IsFindEnabledProperty =
                DependencyProperty.Register( 
                        "IsFindEnabled", 
                        typeof(bool),
                        typeof(FlowDocumentReader), 
                        new FrameworkPropertyMetadata(
                                BooleanBoxes.TrueBox,
                                new PropertyChangedCallback(IsFindEnabledChanged)));
 
        /// 
        ///  
        ///  
        public static readonly DependencyProperty IsPrintEnabledProperty =
                DependencyProperty.Register( 
                        "IsPrintEnabled",
                        typeof(bool),
                        typeof(FlowDocumentReader),
                        new FrameworkPropertyMetadata( 
                                BooleanBoxes.TrueBox,
                                new PropertyChangedCallback(IsPrintEnabledChanged))); 
 
        /// 
        ///  
        /// 
        public static readonly DependencyProperty DocumentProperty =
                DependencyProperty.Register(
                        "Document", 
                        typeof(FlowDocument),
                        typeof(FlowDocumentReader), 
                        new FrameworkPropertyMetadata( 
                                null,
                                new PropertyChangedCallback(DocumentChanged))); 

        /// 
        /// 
        ///  
        public static readonly DependencyProperty ZoomProperty =
                FlowDocumentPageViewer.ZoomProperty.AddOwner( 
                        typeof(FlowDocumentReader), 
                        new FrameworkPropertyMetadata(
                                100d, 
                                new PropertyChangedCallback(ZoomChanged),
                                new CoerceValueCallback(CoerceZoom)));

        ///  
        /// 
        ///  
        public static readonly DependencyProperty MaxZoomProperty = 
                FlowDocumentPageViewer.MaxZoomProperty.AddOwner(
                        typeof(FlowDocumentReader), 
                        new FrameworkPropertyMetadata(
                                200d,
                                new PropertyChangedCallback(MaxZoomChanged),
                                new CoerceValueCallback(CoerceMaxZoom))); 

        ///  
        ///  
        /// 
        public static readonly DependencyProperty MinZoomProperty = 
                FlowDocumentPageViewer.MinZoomProperty.AddOwner(
                        typeof(FlowDocumentReader),
                        new FrameworkPropertyMetadata(
                                80d, 
                                new PropertyChangedCallback(MinZoomChanged)));
 
        ///  
        /// 
        ///  
        public static readonly DependencyProperty ZoomIncrementProperty =
                FlowDocumentPageViewer.ZoomIncrementProperty.AddOwner(
                        typeof(FlowDocumentReader));
 
        /// 
        ///  
        ///  
        private static readonly DependencyPropertyKey CanIncreaseZoomPropertyKey =
                DependencyProperty.RegisterReadOnly( 
                        "CanIncreaseZoom",
                        typeof(bool),
                        typeof(FlowDocumentReader),
                        new FrameworkPropertyMetadata(BooleanBoxes.TrueBox)); 

        ///  
        ///  
        /// 
        public static readonly DependencyProperty CanIncreaseZoomProperty = CanIncreaseZoomPropertyKey.DependencyProperty; 

        /// 
        /// 
        ///  
        private static readonly DependencyPropertyKey CanDecreaseZoomPropertyKey =
                DependencyProperty.RegisterReadOnly( 
                        "CanDecreaseZoom", 
                        typeof(bool),
                        typeof(FlowDocumentReader), 
                        new FrameworkPropertyMetadata(BooleanBoxes.TrueBox));

        /// 
        ///  
        /// 
        public static readonly DependencyProperty CanDecreaseZoomProperty = CanDecreaseZoomPropertyKey.DependencyProperty; 
 
        #endregion Public Dynamic Properties
 
        #endregion Public Properties

        //-------------------------------------------------------------------
        // 
        //  Public Commands
        // 
        //-------------------------------------------------------------------- 

        #region Public Commands 

        /// 
        /// Switch ViewingMode command
        ///  
        public static readonly RoutedUICommand SwitchViewingModeCommand = new RoutedUICommand(SR.Get(SRID.SwitchViewingMode), "SwitchViewingMode", typeof(FlowDocumentReader), null);
 
        #endregion 

        //------------------------------------------------------------------- 
        //
        //  Protected Methods
        //
        //------------------------------------------------------------------- 

        #region Protected Methods 
 
        /// 
        /// Called when print has been completed. 
        /// 
        protected virtual void OnPrintCompleted()
        {
            if (_printInProgress) 
            {
                _printInProgress = false; 
                // Since _printInProgress value is used to determine CanExecute state, we must invalidate that state. 
                CommandManager.InvalidateRequerySuggested();
            } 
        }

        /// 
        /// 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 virtual void OnPrintCommand() 
        {
            if (CurrentViewer != null)
            {
                CurrentViewer.Print(); 
            }
        } 
 
        /// 
        /// Handler for the CancelPrint command. 
        /// 
        protected virtual void OnCancelPrintCommand()
        {
            if (CurrentViewer != null) 
            {
                CurrentViewer.CancelPrint(); 
            } 
        }
 
        /// 
        /// Handler for the IncreaseZoom command.
        /// 
        protected virtual void OnIncreaseZoomCommand() 
        {
            // If can zoom in, increase zoom by the zoom increment value. 
            if (CanIncreaseZoom) 
            {
                Zoom = 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 (CanDecreaseZoom)
            {
                Zoom = Math.Max(Zoom - ZoomIncrement, MinZoom);
            } 
        }
 
        ///  
        /// Handler for the SwitchViewingMode command.
        ///  
        /// Viewing mode.
        protected virtual void OnSwitchViewingModeCommand(FlowDocumentReaderViewingMode viewingMode)
        {
            SwitchViewingModeCore(viewingMode); 
        }
 
        ///  
        /// Called when IsInitialized is set to true.
        ///  
        /// Event arguments
        protected override void OnInitialized(EventArgs e)
        {
            base.OnInitialized(e); 

            // Defer the Is*ViewEnabled & ViewingMode conflict exception. 
            // Otherwise  won't work. 
            if (IsInitialized && !CanSwitchToViewingMode(ViewingMode))
            { 
                throw new ArgumentException(SR.Get(SRID.FlowDocumentReaderViewingModeEnabledConflict));
            }
        }
 
        /// 
        /// Creates AutomationPeer () 
        ///  
        protected override AutomationPeer OnCreateAutomationPeer()
        { 
            return new FlowDocumentReaderAutomationPeer(this);
        }

        ///  
        /// An event reporting that the IsKeyboardFocusWithin property changed.
        ///  
        protected override void OnIsKeyboardFocusWithinChanged(DependencyPropertyChangedEventArgs e) 
        {
            base.OnIsKeyboardFocusWithinChanged(e); 

            // In order to enable selection rendering and other similar services, the embedded viewer
            // needs to get focus, when any part of the control gets focused.
            // But if the focus is within the Document, do not change it. Otherwise it 
            // will interfere with input handling inside the Document.
            if (IsKeyboardFocusWithin && CurrentViewer != null) 
            { 
                bool isFocusWithinDocument = IsFocusWithinDocument();
                if (!isFocusWithinDocument) 
                {
                    ((FrameworkElement)CurrentViewer).Focus();
                }
            } 
        }
 
        ///  
        /// 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) 
        {
            if (e.Handled) { return; } 

            switch (e.Key)
            {
                // Esc -- Close FindToolBar 
                case Key.Escape:
                    if (FindToolBar != null) 
                    { 
                        ToggleFindToolBar(false);
                        e.Handled = true; 
                    }
                    break;

                // F3 -- Invoke Find 
                case 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;
                    }
                    break;
            } 

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

        #endregion Protected Methods 

        //------------------------------------------------------------------- 
        // 
        //  Protected Properties
        // 
        //--------------------------------------------------------------------

        #region Protected Properties
 
        /// 
        /// Returns enumerator to logical children. 
        ///  
        protected internal override IEnumerator LogicalChildren
        { 
            get
            {
                if (HasLogicalChildren && Document != null)
                { 
                    return new SingleChildEnumerator(Document);
                } 
                return EmptyEnumerator.Instance; 
            }
        } 

        #endregion Protected Properties

        //------------------------------------------------------------------- 
        //
        //  Internal Methods 
        // 
        //--------------------------------------------------------------------
 
        #region Internal Methods

        /// 
        /// Allows FrameworkElement to augment the EventRoute. 
        /// 
        internal override bool BuildRouteCore(EventRoute route, RoutedEventArgs args) 
        { 
            // Do not add intermediate ContentElements to the route,
            // because they were added by embedded viewer. 
            return BuildRouteCoreHelper(route, args, false);
        }

        #endregion Internal Methods 

        //-------------------------------------------------------------------- 
        // 
        //  Private Methods
        // 
        //-------------------------------------------------------------------

        #region Private Methods
 
        /// 
        /// Handler for the SwitchViewingMode command. 
        ///  
        /// Viewing mode.
        protected virtual void SwitchViewingModeCore(FlowDocumentReaderViewingMode viewingMode) 
        {
            ITextSelection textSelection = null;
            ContentPosition contentPosition = null;
            IFlowDocumentViewer viewer; 
            FrameworkElement feViewer;
            bool isKeyboardFocusWithin; 
            DependencyObject focusedElement = null; 

            if (_contentHost != null) 
            {
                // Remember the current keyboard focus state.
                isKeyboardFocusWithin = IsKeyboardFocusWithin;
 
                // Detach old viewer
                viewer = _contentHost.Child as IFlowDocumentViewer; 
                if (viewer != null) 
                {
                    // Remember focused element, if the focus is within the Document. 
                    // After switching to a different viewer, this focus needs to be restored.
                    if (isKeyboardFocusWithin)
                    {
                        bool isFocusWithinDocument = IsFocusWithinDocument(); 
                        if (isFocusWithinDocument)
                        { 
                            focusedElement = Keyboard.FocusedElement as DependencyObject; 
                        }
                    } 

                    // Retrieve the current viewing state from the old viewer.
                    textSelection = viewer.TextSelection;
                    contentPosition = viewer.ContentPosition; 

                    // Detach old viewer 
                    DetachViewer(viewer); 
                }
 
                viewer = GetViewerFromMode(viewingMode);
                feViewer = (FrameworkElement)viewer;
                if (viewer != null)
                { 
                    // Attach new viewer
                    _contentHost.Child = feViewer; 
                    AttachViewer(viewer); 

                    // Restore viewing state. 
                    viewer.TextSelection = textSelection;
                    viewer.ContentPosition = contentPosition;

                    // Bring the focus to previously focused element within the document 
                    // or to the current viewer.
                    if (isKeyboardFocusWithin) 
                    { 
                        if (focusedElement is UIElement)
                        { 
                            ((UIElement)focusedElement).Focus();
                        }
                        else if (focusedElement is ContentElement)
                        { 
                            ((ContentElement)focusedElement).Focus();
                        } 
                        else 
                        {
                            feViewer.Focus(); 
                        }
                    }
                }
 
                // Viewer changes invalidates following properties:
                //      - PageCount 
                //      - PageNumber 
                //      - CanGoToPreviousPage
                //      - CanGoToNextPage 
                UpdateReadOnlyProperties(true, true);
            }
        }
 
        /// 
        /// Determines whether focus is within Document. 
        ///  
        private bool IsFocusWithinDocument()
        { 
            DependencyObject focusedElement = Keyboard.FocusedElement as DependencyObject;
            while (focusedElement != null && focusedElement != Document)
            {
                // Skip elements in the control's template (if such exists) and 
                // walk up logical tree to find if the focused element is within
                // the document. 
                FrameworkElement fe = focusedElement as FrameworkElement; 
                if (fe != null && fe.TemplatedParent != null)
                { 
                    focusedElement = fe.TemplatedParent;
                }
                else
                { 
                    focusedElement = LogicalTreeHelper.GetParent(focusedElement);
                } 
            } 
            return (focusedElement != null);
        } 

        /// 
        /// The Document has changed and needs to be updated.
        ///  
        private void DocumentChanged(FlowDocument oldDocument, FlowDocument newDocument)
        { 
            // Cleanup state associated with the old document. 
            if (oldDocument != null)
            { 
                // If Document was added to logical tree before, remove it.
                if (_documentAsLogicalChild)
                {
                    RemoveLogicalChild(oldDocument); 
                }
            } 
 
            // If FlowDocumentReader was created through style, then do not modify
            // the logical tree. Instead, set "core parent" for the Document. 
            if (TemplatedParent != null && newDocument != null && LogicalTreeHelper.GetParent(newDocument) != null)
            {
                // Set the "core parent" back to us.
                ContentOperations.SetParent(newDocument, this); 
                _documentAsLogicalChild = false;
            } 
            else 
            {
                _documentAsLogicalChild = true; 
            }

            // Initialize state associated with the new document.
            if (newDocument != null) 
            {
                // If Document should be part of DocumentViewer's logical tree, add it. 
                if (_documentAsLogicalChild) 
                {
                    AddLogicalChild(newDocument); 
                }
            }

            // Attach document to the current viewer. 
            if (CurrentViewer != null)
            { 
                CurrentViewer.SetDocument(newDocument); 
            }
 
            // Document invalidation invalidates following properties:
            //      - PageCount
            //      - PageNumber
            //      - CanGoToPreviousPage 
            //      - CanGoToNextPage
            UpdateReadOnlyProperties(true, true); 
 
            // Update the toolbar with our current document state.
            if (!CanShowFindToolBar) 
            {
                // Disable FindToolBar, if the content does not support it.
                if (FindToolBar != null)
                { 
                    ToggleFindToolBar(false);
                } 
            } 

            // Document is also represented as Automation child. Need to invalidate peer to force update. 
            FlowDocumentReaderAutomationPeer peer = UIElementAutomationPeer.FromElement(this) as FlowDocumentReaderAutomationPeer;
            if (peer != null)
            {
                peer.InvalidatePeer(); 
            }
        } 
 
        /// 
        /// Detach embedded viewer form the reader control. 
        /// 
        private void DetachViewer(IFlowDocumentViewer viewer)
        {
            Invariant.Assert(viewer != null && viewer is FrameworkElement); 
            FrameworkElement feViewer = (FrameworkElement)viewer;
            // Clear property bindings. 
            BindingOperations.ClearBinding(feViewer, ZoomProperty); 
            BindingOperations.ClearBinding(feViewer, MaxZoomProperty);
            BindingOperations.ClearBinding(feViewer, MinZoomProperty); 
            BindingOperations.ClearBinding(feViewer, ZoomIncrementProperty);
            // Unregister event handlers.
            viewer.PageCountChanged -= new EventHandler(OnPageCountChanged);
            viewer.PageNumberChanged -= new EventHandler(OnPageNumberChanged); 
            viewer.PrintStarted -= new EventHandler(OnViewerPrintStarted);
            viewer.PrintCompleted -= new EventHandler(OnViewerPrintCompleted); 
            // Clear TemplatedParent 
            //feViewer._templatedParent = null;
            // Detach document 
            viewer.SetDocument(null);
        }

        ///  
        /// Attach embedded viewer to the reader control.
        ///  
        private void AttachViewer(IFlowDocumentViewer viewer) 
        {
            Invariant.Assert(viewer != null && viewer is FrameworkElement); 
            FrameworkElement feViewer = (FrameworkElement)viewer;
            // Set document
            viewer.SetDocument(Document);
            // Set TemplatedParent 
            //feViewer._templatedParent = TemplatedParent;
            // Register event handlers. 
            viewer.PageCountChanged += new EventHandler(OnPageCountChanged); 
            viewer.PageNumberChanged += new EventHandler(OnPageNumberChanged);
            viewer.PrintStarted += new EventHandler(OnViewerPrintStarted); 
            viewer.PrintCompleted += new EventHandler(OnViewerPrintCompleted);
            // Create property bindings.
            CreateTwoWayBinding(feViewer, ZoomProperty, "Zoom");
            CreateTwoWayBinding(feViewer, MaxZoomProperty, "MaxZoom"); 
            CreateTwoWayBinding(feViewer, MinZoomProperty, "MinZoom");
            CreateTwoWayBinding(feViewer, ZoomIncrementProperty, "ZoomIncrement"); 
        } 

        ///  
        /// Create two way property binding.
        /// 
        private void CreateTwoWayBinding(FrameworkElement fe, DependencyProperty dp, string propertyPath)
        { 
            Binding binding = new Binding(propertyPath);
            binding.Mode = BindingMode.TwoWay; 
            binding.Source = this; 
            fe.SetBinding(dp, binding);
        } 

        /// 
        /// Determines whether can switch to specified ViewingMode or not.
        ///  
        private bool CanSwitchToViewingMode(FlowDocumentReaderViewingMode mode)
        { 
            bool canSwitch = false; 
            switch (mode)
            { 
                case FlowDocumentReaderViewingMode.Page:
                    canSwitch = IsPageViewEnabled;
                    break;
                case FlowDocumentReaderViewingMode.TwoPage: 
                    canSwitch = IsTwoPageViewEnabled;
                    break; 
                case FlowDocumentReaderViewingMode.Scroll: 
                    canSwitch = IsScrollViewEnabled;
                    break; 
            }
            return canSwitch;
        }
 
        /// 
        /// Retrieves viewer form specified ViewingMode. 
        ///  
        private IFlowDocumentViewer GetViewerFromMode(FlowDocumentReaderViewingMode mode)
        { 
            IFlowDocumentViewer viewer = null;
            switch (mode)
            {
                case FlowDocumentReaderViewingMode.Page: 
                    if (_pageViewer == null)
                    { 
                        _pageViewer = new ReaderPageViewer(); 
                        _pageViewer.SetResourceReference(StyleProperty, PageViewStyleKey);
                        _pageViewer.Name = "PageViewer"; 
                        CommandManager.AddPreviewCanExecuteHandler(_pageViewer, new CanExecuteRoutedEventHandler(PreviewCanExecuteRoutedEventHandler));
                    }
                    viewer = _pageViewer;
                    break; 
                case FlowDocumentReaderViewingMode.TwoPage:
                    if (_twoPageViewer == null) 
                    { 
                        _twoPageViewer = new ReaderTwoPageViewer();
                        _twoPageViewer.SetResourceReference(StyleProperty, TwoPageViewStyleKey); 
                        _twoPageViewer.Name = "TwoPageViewer";
                        CommandManager.AddPreviewCanExecuteHandler(_twoPageViewer, new CanExecuteRoutedEventHandler(PreviewCanExecuteRoutedEventHandler));
                    }
                    viewer = _twoPageViewer; 
                    break;
                case FlowDocumentReaderViewingMode.Scroll: 
                    if (_scrollViewer == null) 
                    {
                        _scrollViewer = new ReaderScrollViewer(); 
                        _scrollViewer.SetResourceReference(StyleProperty, ScrollViewStyleKey);
                        _scrollViewer.Name = "ScrollViewer";
                        CommandManager.AddPreviewCanExecuteHandler(_scrollViewer, new CanExecuteRoutedEventHandler(PreviewCanExecuteRoutedEventHandler));
                    } 
                    viewer = _scrollViewer;
                    break; 
            } 
            return viewer;
        } 

        /// 
        /// Update values for readonly properties.
        ///  
        /// Whether PageCount has been changed.
        /// Whether PageNumber has been changed. 
        private void UpdateReadOnlyProperties(bool pageCountChanged, bool pageNumberChanged) 
        {
            if (pageCountChanged) 
            {
                SetValue(PageCountPropertyKey, (CurrentViewer != null) ? CurrentViewer.PageCount : 0);
            }
 
            if (pageNumberChanged)
            { 
                SetValue(PageNumberPropertyKey, (CurrentViewer != null) ? CurrentViewer.PageNumber : 0); 
                SetValue(CanGoToPreviousPagePropertyKey, (CurrentViewer != null) ? CurrentViewer.CanGoToPreviousPage : false);
            } 

            if (pageCountChanged || pageNumberChanged)
            {
                SetValue(CanGoToNextPagePropertyKey, (CurrentViewer != null) ? CurrentViewer.CanGoToNextPage : false); 
            }
        } 
 
        /// 
        /// Event handler for IFlowDocumentViewer.PageCountChanged. 
        /// 
        private void OnPageCountChanged(object sender, EventArgs e)
        {
            Invariant.Assert(CurrentViewer != null && sender == CurrentViewer); 
            UpdateReadOnlyProperties(true, false);
        } 
 
        /// 
        /// Event handler for IFlowDocumentViewer.PageNumberChanged. 
        /// 
        private void OnPageNumberChanged(object sender, EventArgs e)
        {
            Invariant.Assert(CurrentViewer != null && sender == CurrentViewer); 
            UpdateReadOnlyProperties(false, true);
        } 
 
        /// 
        /// Event handler for IFlowDocumentViewer.PrintStarted. 
        /// 
        private void OnViewerPrintStarted(object sender, EventArgs e)
        {
            Invariant.Assert(CurrentViewer != null && sender == CurrentViewer); 
            _printInProgress = true;
            // Since _printInProgress value is used to determine CanExecute state, we must invalidate that state. 
            CommandManager.InvalidateRequerySuggested(); 
        }
 
        /// 
        /// Event handler for IFlowDocumentViewer.PrintCompleted.
        /// 
        private void OnViewerPrintCompleted(object sender, EventArgs e) 
        {
            Invariant.Assert(CurrentViewer != null && sender == CurrentViewer); 
            OnPrintCompleted(); 
        }
 
        /// 
        /// Convert object value to FlowDocumentReaderViewingMode.
        /// 
        private bool ConvertToViewingMode(object value, out FlowDocumentReaderViewingMode mode) 
        {
            bool success; 
            if (value is FlowDocumentReaderViewingMode) 
            {
                mode = (FlowDocumentReaderViewingMode)value; 
                success = true;
            }
            else if (value is String)
            { 
                String str = (String)value;
                if (str == FlowDocumentReaderViewingMode.Page.ToString()) 
                { 
                    mode = FlowDocumentReaderViewingMode.Page;
                    success = true; 
                }
                else if (str == FlowDocumentReaderViewingMode.TwoPage.ToString())
                {
                    mode = FlowDocumentReaderViewingMode.TwoPage; 
                    success = true;
                } 
                else if (str == FlowDocumentReaderViewingMode.Scroll.ToString()) 
                {
                    mode = FlowDocumentReaderViewingMode.Scroll; 
                    success = true;
                }
                else
                { 
                    mode = FlowDocumentReaderViewingMode.Page;
                    success = false; 
                } 
            }
            else 
            {
                mode = FlowDocumentReaderViewingMode.Page;
                success = false;
            } 
            return success;
        } 
 
        /// 
        /// Enables/disables the FindToolBar. 
        /// 
        /// Whether to enable/disable FindToolBar.
        private void ToggleFindToolBar(bool enable)
        { 
            Invariant.Assert(enable == (FindToolBar == null));
 
            // Command event for toggle button is only fired in OnClick - Therefore we just need to change the state 
            if(_findButton != null && _findButton.IsChecked.HasValue && _findButton.IsChecked.Value != enable)
            { 
                _findButton.IsChecked = enable;
            }
            DocumentViewerHelper.ToggleFindToolBar(_findToolBarHost, new EventHandler(OnFindInvoked), enable);
        } 

        #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: SwitchViewingMode
            CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentReader), FlowDocumentReader.SwitchViewingModeCommand, 
                executedHandler, canExecuteHandler, SRID.KeySwitchViewingMode, SRID.KeySwitchViewingModeDisplayString);
 
            // Command: ApplicationCommands.Find 
            CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentReader), ApplicationCommands.Find,
                executedHandler, canExecuteHandler); 

            // Command: ApplicationCommands.Print
            CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentReader), ApplicationCommands.Print,
                executedHandler, canExecuteHandler); 

            // Command: ApplicationCommands.CancelPrint 
            CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentReader), ApplicationCommands.CancelPrint, 
                executedHandler, canExecuteHandler);
 
            // Command: NavigationCommands.PreviousPage
            CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentReader), NavigationCommands.PreviousPage,
                executedHandler, canExecuteHandler);
 
            // Command: NavigationCommands.NextPage
            CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentReader), NavigationCommands.NextPage, 
                executedHandler, canExecuteHandler); 

            // Command: NavigationCommands.FirstPage 
            CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentReader), NavigationCommands.FirstPage,
                executedHandler, canExecuteHandler);

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

            // Command: NavigationCommands.DecreaseZoom
            CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentReader), NavigationCommands.DecreaseZoom, 
                executedHandler, canExecuteHandler, new KeyGesture(Key.OemMinus, ModifierKeys.Control));
        } 
 
        /// 
        /// Central handler for CanExecute events fired by Commands directed at FlowDocumentReader. 
        /// 
        /// The target of this Command, expected to be FlowDocumentReader
        /// The event arguments for this event.
        private static void CanExecuteRoutedEventHandler(object target, CanExecuteRoutedEventArgs args) 
        {
            FlowDocumentReader viewer = target as FlowDocumentReader; 
            Invariant.Assert(viewer != null, "Target of CanExecuteRoutedEventHandler must be FlowDocumentReader."); 
            Invariant.Assert(args != null, "args cannot be null.");
 
            // FlowDocumentReader is capable of execution of the majority of its commands.
            // Special rules:
            // a) during printing only CancelPrint is enabled.
            // b) Find command is enabled only when FindToolBar is enabled. 
            // c) Print command is enabled when Document is attached and printing is enabled.
            // d) CancelPrint command is enabled only during printing. 
            // e) SwitchViewingMode command is enabled if the viewing mode is enabled, or 
            //    the command has no parameters (will switch to the next available view).
            if (!viewer._printInProgress) 
            {
                if (args.Command == FlowDocumentReader.SwitchViewingModeCommand)
                {
                    // This command is enabled if the viewing mode is enabled, or the command 
                    // has no parameters (will switch to the next available view).
                    FlowDocumentReaderViewingMode mode; 
                    if (viewer.ConvertToViewingMode(args.Parameter, out mode)) 
                    {
                        args.CanExecute = viewer.CanSwitchToViewingMode(mode); 
                    }
                    else
                    {
                        args.CanExecute = (args.Parameter == null); 
                    }
                } 
                else if (args.Command == ApplicationCommands.Find) 
                {
                    args.CanExecute = viewer.CanShowFindToolBar; 
                }
                else if (args.Command == ApplicationCommands.Print)
                {
                    args.CanExecute = (viewer.Document != null) && viewer.IsPrintEnabled; 
                }
                else if (args.Command == ApplicationCommands.CancelPrint) 
                { 
                    args.CanExecute = false;
                } 
                else
                {
                    args.CanExecute = true;
                } 
            }
            else 
            { 
                args.CanExecute = (args.Command == ApplicationCommands.CancelPrint);
            } 
        }

        /// 
        /// Central handler for all ExecuteEvents fired by Commands directed at FlowDocumentReader. 
        /// 
        /// The target of this Command, expected to be FlowDocumentReader. 
        /// The event arguments associated with this event. 
        private static void ExecutedRoutedEventHandler(object target, ExecutedRoutedEventArgs args)
        { 
            FlowDocumentReader viewer = target as FlowDocumentReader;
            Invariant.Assert(viewer != null, "Target of ExecutedRoutedEventHandler must be FlowDocumentReader.");
            Invariant.Assert(args != null, "args cannot be null.");
 
            if (args.Command == FlowDocumentReader.SwitchViewingModeCommand)
            { 
                viewer.TrySwitchViewingMode(args.Parameter); 
            }
            else if (args.Command == ApplicationCommands.Find) 
            {
                viewer.OnFindCommand();
            }
            else if (args.Command == ApplicationCommands.Print) 
            {
                viewer.OnPrintCommand(); 
            } 
            else if (args.Command == ApplicationCommands.CancelPrint)
            { 
                viewer.OnCancelPrintCommand();
            }
            else if (args.Command == NavigationCommands.IncreaseZoom)
            { 
                viewer.OnIncreaseZoomCommand();
            } 
            else if (args.Command == NavigationCommands.DecreaseZoom) 
            {
                viewer.OnDecreaseZoomCommand(); 
            }
            else if (args.Command == NavigationCommands.PreviousPage)
            {
                viewer.OnPreviousPageCommand(); 
            }
            else if (args.Command == NavigationCommands.NextPage) 
            { 
                viewer.OnNextPageCommand();
            } 
            else if (args.Command == NavigationCommands.FirstPage)
            {
                viewer.OnFirstPageCommand();
            } 
            else if (args.Command == NavigationCommands.LastPage)
            { 
                viewer.OnLastPageCommand(); 
            }
            else 
            {
                Invariant.Assert(false, "Command not handled in ExecutedRoutedEventHandler.");
            }
        } 

        ///  
        /// Changes the current viewing mode. 
        /// 
        private void TrySwitchViewingMode(object parameter) 
        {
            FlowDocumentReaderViewingMode mode;
            // Convert command parameter to viewing mode value.
            // If parameter is not provided, the viewing mode is the next one available. 
            // If parameter cannot be converted, the command is ignored.
            if (!ConvertToViewingMode(parameter, out mode)) 
            { 
                if (parameter == null)
                { 
                    mode = (FlowDocumentReaderViewingMode)((((int)ViewingMode) + 1) % 3);
                }
                else
                { 
                    return;
                } 
            } 
            // If the current ViewingMode is disabled, go to next one.
            while (!CanSwitchToViewingMode(mode)) 
            {
                mode = (FlowDocumentReaderViewingMode)((((int)mode) + 1) % 3);
            }
            // Set new ViewingMode value. 
            ViewingMode = mode;
        } 
 
        /// 
        /// Handler for the PreviousPage command. 
        /// 
        private void OnPreviousPageCommand()
        {
            if (CurrentViewer != null) 
            {
                CurrentViewer.PreviousPage(); 
            } 
        }
 
        /// 
        /// Handler for the NextPage command.
        /// 
        private void OnNextPageCommand() 
        {
            if (CurrentViewer != null) 
            { 
                CurrentViewer.NextPage();
            } 
        }

        /// 
        /// Handler for the FirstPage command. 
        /// 
        private void OnFirstPageCommand() 
        { 
            if (CurrentViewer != null)
            { 
                CurrentViewer.FirstPage();
            }
        }
 
        /// 
        /// Handler for the LastPage command. 
        ///  
        private void OnLastPageCommand()
        { 
            if (CurrentViewer != null)
            {
                CurrentViewer.LastPage();
            } 
        }
 
        ///  
        /// 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; 
            TextEditor textEditor = TextEditor; 
            FindToolBar findToolBar = FindToolBar;
 
            if (findToolBar != null && 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.
                if (CurrentViewer != null && CurrentViewer is UIElement) 
                { 
                    ((UIElement)CurrentViewer).Focus();
                } 

                findResult = DocumentViewerHelper.Find(findToolBar, textEditor, textEditor.TextView, textEditor.TextView);

                // If we found something, bring it into the view. Otherwise alert the user. 
                if ((findResult != null) && (!findResult.IsEmpty))
                { 
                    // Bring find result into view. 
                    if (CurrentViewer != null)
                    { 
                        CurrentViewer.ShowFindResult(findResult);
                    }
                }
                else 
                {
                    DocumentViewerHelper.ShowFindUnsuccessfulMessage(findToolBar); 
                } 
            }
        } 

        /// 
        /// Disable commands on IFlowDocumentViewer when this funcionality is explicitly
        /// disabled on the reader control. 
        /// 
        private void PreviewCanExecuteRoutedEventHandler(object target, CanExecuteRoutedEventArgs args) 
        { 
            if (args.Command == ApplicationCommands.Find)
            { 
                // Find is handled by FlowDocumentReader.
                args.CanExecute = false;
                args.Handled = true;
            } 
            else if (args.Command == ApplicationCommands.Print)
            { 
                args.CanExecute = IsPrintEnabled; 
                args.Handled = !IsPrintEnabled;
            } 
        }

        /// 
        /// Called when a key event occurs. 
        /// 
        private static void KeyDownHandler(object sender, KeyEventArgs e) 
        { 
            DocumentViewerHelper.KeyDownHelper(e, ((FlowDocumentReader)sender)._findToolBarHost);
        } 

        #endregion Commands

        #region Static Methods 

        ///  
        /// ViewingMode has been changed. 
        /// 
        private static void ViewingModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            Invariant.Assert(d != null && d is FlowDocumentReader);
            FlowDocumentReader viewer = (FlowDocumentReader)d;
            if (viewer.CanSwitchToViewingMode((FlowDocumentReaderViewingMode)e.NewValue)) 
            {
                viewer.SwitchViewingModeCore((FlowDocumentReaderViewingMode)e.NewValue); 
            } 
            else if (viewer.IsInitialized)
            { 
                throw new ArgumentException(SR.Get(SRID.FlowDocumentReaderViewingModeEnabledConflict));
            }

            // Fire automation events if automation is active. 
            FlowDocumentReaderAutomationPeer peer = UIElementAutomationPeer.FromElement(viewer) as FlowDocumentReaderAutomationPeer;
            if (peer != null) 
            { 
                peer.RaiseCurrentViewChangedEvent((FlowDocumentReaderViewingMode)e.NewValue, (FlowDocumentReaderViewingMode)e.OldValue);
            } 
        }

        /// 
        /// Validate value of ViewingMode property. 
        /// 
        private static bool IsValidViewingMode(object o) 
        { 
            FlowDocumentReaderViewingMode value = (FlowDocumentReaderViewingMode)o;
            return (value == FlowDocumentReaderViewingMode.Page || 
                    value == FlowDocumentReaderViewingMode.TwoPage ||
                    value == FlowDocumentReaderViewingMode.Scroll);
        }
 
        /// 
        /// One of viewing modes has been enabled/disabled. 
        ///  
        private static void ViewingModeEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        { 
            Invariant.Assert(d != null && d is FlowDocumentReader);
            FlowDocumentReader viewer = (FlowDocumentReader)d;

            // Cannot disable all viewing modes. 
            if (!viewer.IsPageViewEnabled &&
                !viewer.IsTwoPageViewEnabled && 
                !viewer.IsScrollViewEnabled) 
            {
                throw new ArgumentException(SR.Get(SRID.FlowDocumentReaderCannotDisableAllViewingModes)); 
            }

            // Cannot disable the current viewing mode.
            if (viewer.IsInitialized && !viewer.CanSwitchToViewingMode(viewer.ViewingMode)) 
            {
                throw new ArgumentException(SR.Get(SRID.FlowDocumentReaderViewingModeEnabledConflict)); 
            } 

            // Fire automation events if automation is active. 
            FlowDocumentReaderAutomationPeer peer = UIElementAutomationPeer.FromElement(viewer) as FlowDocumentReaderAutomationPeer;
            if (peer != null)
            {
                peer.RaiseSupportedViewsChangedEvent(e); 
            }
        } 
 
        /// 
        /// IsFindEnabled value has changed. 
        /// 
        private static void IsFindEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Invariant.Assert(d != null && d is FlowDocumentReader); 
            FlowDocumentReader viewer = (FlowDocumentReader)d;
 
            // Update the toolbar with our current state. 
            if (!viewer.CanShowFindToolBar)
            { 
                if (viewer.FindToolBar != null)
                {
                    viewer.ToggleFindToolBar(false);
                } 
            }
 
            // Since IsFindEnabled state is used to determine CanExecute state, we must invalidate that state. 
            CommandManager.InvalidateRequerySuggested();
        } 

        /// 
        /// IsPrintEnabled value has changed.
        ///  
        private static void IsPrintEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        { 
            Invariant.Assert(d != null && d is FlowDocumentReader); 
            FlowDocumentReader viewer = (FlowDocumentReader)d;
 
            // Since IsPrintEnabled state is used to determine CanExecute state, we must invalidate that state.
            CommandManager.InvalidateRequerySuggested();
        }
 
        /// 
        /// The Document has changed and needs to be updated. 
        ///  
        private static void DocumentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        { 
            Invariant.Assert(d != null && d is FlowDocumentReader);
            FlowDocumentReader viewer = (FlowDocumentReader)d;
            viewer.DocumentChanged((FlowDocument)e.OldValue, (FlowDocument)e.NewValue);
 
            // Since Document state is used to determine CanExecute state, we must invalidate that state.
            CommandManager.InvalidateRequerySuggested(); 
        } 

        ///  
        /// The Zoom has changed and needs to be updated.
        /// 
        private static void ZoomChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        { 
            Invariant.Assert(d != null && d is FlowDocumentReader);
            FlowDocumentReader viewer = (FlowDocumentReader)d; 
            if (!DoubleUtil.AreClose((double)e.OldValue, (double)e.NewValue)) 
            {
                // If zoom has been changed, CanIncrease/DecreaseZoom property need to be updated. 
                viewer.SetValue(CanIncreaseZoomPropertyKey, BooleanBoxes.Box(DoubleUtil.GreaterThan(viewer.MaxZoom, viewer.Zoom)));
                viewer.SetValue(CanDecreaseZoomPropertyKey, BooleanBoxes.Box(DoubleUtil.LessThan(viewer.MinZoom, viewer.Zoom)));
            }
        } 

        ///  
        /// Coerce Zoom with Max/MinZoom, MinZoom works as the baseline. 
        /// 
        private static object CoerceZoom(DependencyObject d, object value) 
        {
            Invariant.Assert(d != null && d is FlowDocumentReader);
            FlowDocumentReader viewer = (FlowDocumentReader)d;
 
            double zoom = (double)value;
 
            double maxZoom = viewer.MaxZoom; 
            if (DoubleUtil.LessThan(maxZoom, zoom))
            { 
                return maxZoom;
            }

            double minZoom = viewer.MinZoom; 
            if (DoubleUtil.GreaterThan(minZoom, zoom))
            { 
                return minZoom; 
            }
 
            return value;
        }

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

            viewer.CoerceValue(ZoomProperty);
            viewer.SetValue(CanIncreaseZoomPropertyKey, BooleanBoxes.Box(DoubleUtil.GreaterThan(viewer.MaxZoom, viewer.Zoom))); 
        }
 
        ///  
        /// MaxZoom need to be coerced if MinZoom > MaxZoom
        ///  
        private static object CoerceMaxZoom(DependencyObject d, object value)
        {
            Invariant.Assert(d != null && d is FlowDocumentReader);
            FlowDocumentReader viewer = (FlowDocumentReader)d; 

            double min = viewer.MinZoom; 
            return ((double)value < min) ? min : value; 
        }
 
        /// 
        /// The MinZoom has changed and needs to be updated.
        /// 
        private static void MinZoomChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            Invariant.Assert(d != null && d is FlowDocumentReader); 
            FlowDocumentReader viewer = (FlowDocumentReader)d; 

            viewer.CoerceValue(MaxZoomProperty); 
            viewer.CoerceValue(ZoomProperty);
            viewer.SetValue(CanDecreaseZoomPropertyKey, BooleanBoxes.Box(DoubleUtil.LessThan(viewer.MinZoom, viewer.Zoom)));
        }
 
        /// 
        /// 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)); 
        }
 
        #endregion Static Methods 

        #endregion Private Methods 

        //--------------------------------------------------------------------
        //
        //  Private Properties 
        //
        //------------------------------------------------------------------- 
 
        #region Private Properties
 
        /// 
        /// Whether FindToolBar can be enabled.
        /// 
        private bool CanShowFindToolBar 
        {
            get { return ((_findToolBarHost != null) && IsFindEnabled && (Document != null)); } 
        } 

        ///  
        /// Returns TextEditor, if availabe.
        /// 
        private TextEditor TextEditor
        { 
            get
            { 
                TextEditor textEditor = null; 
                IFlowDocumentViewer currentViewer = CurrentViewer;
                if (currentViewer != null && currentViewer.TextSelection != null) 
                {
                    textEditor = currentViewer.TextSelection.TextEditor;
                }
                return textEditor; 
            }
        } 
 
        /// 
        /// Returns FindToolBar, if enabled. 
        /// 
        private FindToolBar FindToolBar
        {
            get { return (_findToolBarHost != null) ? _findToolBarHost.Child as FindToolBar : null; } 
        }
 
        ///  
        /// Returns the current content viewer.
        ///  
        private IFlowDocumentViewer CurrentViewer
        {
            get
            { 
                if (_contentHost != null)
                { 
                    return (IFlowDocumentViewer)_contentHost.Child; 
                }
                return null; 
            }
        }

        #endregion Private Properties 

        //------------------------------------------------------------------- 
        // 
        //  Private Fields
        // 
        //-------------------------------------------------------------------

        #region Private Fields
 
        private Decorator _contentHost;                 // Host for content viewer
        private Decorator _findToolBarHost;             // Host for FindToolBar 
        private ToggleButton _findButton;               // Find toggle button 
        private ReaderPageViewer _pageViewer;           // Viewer for Page viewing mode
        private ReaderTwoPageViewer _twoPageViewer;     // Viewer for TwoPage viewing mode 
        private ReaderScrollViewer _scrollViewer;       // Viewer for Scroll viewing mode
        private bool _documentAsLogicalChild;           // Is Document part of logical tree
        private bool _printInProgress;                  // Whether print is currently in progress.
 
        private const string _contentHostTemplateName = "PART_ContentHost";         // Name for ContentHost
        private const string _findToolBarHostTemplateName = "PART_FindToolBarHost"; // Name for the Find ToolBar host 
        private const string _findButtonTemplateName = "FindButton"; // Name for the Find Button 

        #endregion Private Fields 

        //--------------------------------------------------------------------
        //
        //  IAddChild Members 
        //
        //------------------------------------------------------------------- 
 
        #region IAddChild Members
 
        /// 
        /// Called to add the object as a Child.
        /// 
        /// Object to add as a child. 
        /// FlowDocumentScrollViewer only supports a single child of type IDocumentPaginator.
        void IAddChild.AddChild(Object value) 
        { 
            if (value == null)
            { 
                throw new ArgumentNullException("value");
            }
            // Check if Content has already been set.
            if (this.Document != null) 
            {
                throw new ArgumentException(SR.Get(SRID.FlowDocumentReaderCanHaveOnlyOneChild)); 
            } 
            if (!(value is FlowDocument))
            { 
                throw new ArgumentException(SR.Get(SRID.UnexpectedParameterType, value.GetType(), typeof(FlowDocument)), "value");
            }
            Document = value as FlowDocument;
        } 

        ///  
        /// Called when text appears under the tag in markup 
        /// 
        /// Text to add to the Object. 
        /// FlowDocumentScrollViewer does not support Text children.
        void IAddChild.AddText(string text)
        {
            XamlSerializerUtil.ThrowIfNonWhiteSpaceInAddText(text, this); 
        }
 
        #endregion IAddChild Members 

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

        #region IJournalState Members 
 
        [Serializable]
        private class JournalState : CustomJournalStateInternal 
        {
            public JournalState(int contentPosition, LogicalDirection contentPositionDirection, double zoom, FlowDocumentReaderViewingMode viewingMode)
            {
                ContentPosition = contentPosition; 
                ContentPositionDirection = contentPositionDirection;
                Zoom = zoom; 
                ViewingMode = viewingMode; 
            }
            public int ContentPosition; 
            public LogicalDirection ContentPositionDirection;
            public double Zoom;
            public FlowDocumentReaderViewingMode ViewingMode;
        } 

        ///  
        ///  
        /// 
        CustomJournalStateInternal IJournalState.GetJournalState(JournalReason journalReason) 
        {
            int cp = -1;
            LogicalDirection cpDirection = LogicalDirection.Forward;
            IFlowDocumentViewer viewer = CurrentViewer; 
            if (viewer != null)
            { 
                TextPointer contentPosition = viewer.ContentPosition as TextPointer; 
                if (contentPosition != null)
                { 
                    cp = contentPosition.Offset;
                    cpDirection = contentPosition.LogicalDirection;
                }
            } 
            return new JournalState(cp, cpDirection, Zoom, ViewingMode);
        } 
 
        /// 
        ///  
        /// 
        void IJournalState.RestoreJournalState(CustomJournalStateInternal state)
        {
            JournalState viewerState = state as JournalState; 
            if (state != null)
            { 
                Zoom = viewerState.Zoom; 
                ViewingMode = viewerState.ViewingMode;
                if (viewerState.ContentPosition != -1) 
                {
                    IFlowDocumentViewer viewer = CurrentViewer;
                    FlowDocument document = Document;
                    if (viewer != null && document != null) 
                    {
                        TextContainer textContainer = document.StructuralCache.TextContainer; 
                        if (viewerState.ContentPosition <= textContainer.SymbolCount) 
                        {
                            TextPointer contentPosition = textContainer.CreatePointerAtOffset(viewerState.ContentPosition, viewerState.ContentPositionDirection); 
                            viewer.ContentPosition = 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

        //------------------------------------------------------------------- 
        //
        //  Style Keys 
        // 
        //-------------------------------------------------------------------
 
        #region Style Keys

        /// 
        /// Key used to mark the style for use by the PageView 
        /// 
        private static ResourceKey PageViewStyleKey 
        { 
            get
            { 
                if (_pageViewStyleKey == null)
                {
                    _pageViewStyleKey = new ComponentResourceKey(typeof(PresentationUIStyleResources), "PUIPageViewStyleKey");
                } 

                return _pageViewStyleKey; 
            } 
        }
 
        /// 
        /// Key used to mark the style for use by the TwoPageView
        /// 
        private static ResourceKey TwoPageViewStyleKey 
        {
            get 
            { 
                if (_twoPageViewStyleKey == null)
                { 
                    _twoPageViewStyleKey = new ComponentResourceKey(typeof(PresentationUIStyleResources), "PUITwoPageViewStyleKey");
                }

                return _twoPageViewStyleKey; 
            }
        } 
 
        /// 
        /// Key used to mark the style for use by the ScrollView 
        /// 
        private static ResourceKey ScrollViewStyleKey
        {
            get 
            {
                if (_scrollViewStyleKey == null) 
                { 
                    _scrollViewStyleKey = new ComponentResourceKey(typeof(PresentationUIStyleResources), "PUIScrollViewStyleKey");
                } 

                return _scrollViewStyleKey;
            }
        } 

 
        private static ComponentResourceKey _pageViewStyleKey; 
        private static ComponentResourceKey _twoPageViewStyleKey;
        private static ComponentResourceKey _scrollViewStyleKey; 

        #endregion
    }
 
    /// 
    /// 
 
    public enum FlowDocumentReaderViewingMode
    { 
        /// 
        ///

        Page, 

        ///  
        /// 

        TwoPage, 

        /// 
        ///
 
        Scroll
    } 
} 

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