RichTextBox.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / System / Windows / Controls / RichTextBox.cs / 3 / RichTextBox.cs

                            //---------------------------------------------------------------------------- 
//
// File: RichTextBox.cs
//
// Copyright (C) Microsoft Corporation.  All rights reserved. 
//
// Description: The stock rich text editing control. 
// 
//---------------------------------------------------------------------------
 
namespace System.Windows.Controls
{
    using MS.Internal;
    using MS.Internal.Documents; 
    using System.Windows.Threading;
    using System.Windows.Input; // KeyboardNavigation 
    using System.ComponentModel; // DefaultValue 
    using System.Windows.Controls.Primitives; // TextBoxBase
    using System.Windows.Documents; // TextEditor 
    using System.Windows.Automation.Peers; // AutomationPattern
    using System.Windows.Media; // GlyphRun
    using System.Windows.Markup; // IAddChild
    using System.Collections; // IEnumerator 
    using System.Collections.ObjectModel; // ReadOnlyCollection
    using MS.Internal.Automation;     // For TextAdaptor 
    using MS.Internal.Controls; // EmptyEnumerator 

    ///  
    /// RichTextBox control
    /// 
    [Localizability(LocalizationCategory.Inherit)]
    [ContentProperty("Document")] 
    public class RichTextBox : TextBoxBase, IAddChild
    { 
        // ----------------------------------------------------------- 
        //
        // Constructors 
        //
        // -----------------------------------------------------------

        #region Constructors 

        ///  
        /// Static constructor for RichTextBox. 
        /// 
        static RichTextBox() 
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(RichTextBox), new FrameworkPropertyMetadata(typeof(RichTextBox)));
            _dType = DependencyObjectType.FromSystemTypeInternal(typeof(RichTextBox));
 
            // Default value for AcceptsReturn is true
            KeyboardNavigation.AcceptsReturnProperty.OverrideMetadata(typeof(RichTextBox), new FrameworkPropertyMetadata(true)); 
 
            // Default value for AutoWordSelection is false.  We want true.
            TextBoxBase.AutoWordSelectionProperty.OverrideMetadata(typeof(RichTextBox), new FrameworkPropertyMetadata(true)); 

            // We need to transfer all character formatting properties and some behavioral inheriting properties
            // from RichTextBox level into its FlowDocument.
            // For this purpose we set listeners for all these properties: 
            HookupInheritablePropertyListeners();
        } 
 
        /// 
        /// Initializes a new instance of RichTextBox control. 
        /// 
        /// 
        /// Creates implicit instance of a FlowDocument as its oinitial content.
        /// The initial document will contain one Paragraph with an empty Run in it. 
        /// 
        public RichTextBox() 
            : this(null) 
        {
        } 

        /// 
        /// Initializes a new instance of RichTextBox control ans specifies a FlowDocument as its content
        ///  
        /// 
        /// A FlowDocument specified as a content for this instance of RichTextBox. 
        ///  
        public RichTextBox(FlowDocument document)
            : base() 
        {
            // Register static editing command handlers.
            // This only has an effect that first time we make the call.
            // We don't use the static ctor because there are cases 
            // where another control will want to alias our properties
            // but doesn't need this overhead. 
            TextEditor.RegisterCommandHandlers(typeof(RichTextBox), /*acceptsRichContent:*/true, /*readOnly*/false, /*registerEventListeners*/false); 

            // Create TextContainer and TextEditor associated with it 
            if (document == null)
            {
                document = new FlowDocument();
                document.Blocks.Add(new Paragraph()); 

                // Mark the document as implicit. 
                // This flag will affect these behaviors: 
                //  a) RichTextBox serialization will not output FlowDocument child if it is implicit and still empty
                //  b) IAddChild will allow adding the first child (which will become non-implicit, and would not allow the subsecuent additions) 
                //  c) Property inheritance from RichTextBox to its FlowDocument will work only for implicit document
                // This call must be done after Document assignment, as it always clears the _implicitDocument field.
                _implicitDocument = true;
            } 

            // Initialize the Document property. 
            // Note that _implicitDocument flag was set to true/false just before that. 
            // The peemptive flag setting has its effect only when _document is null (this case only),
            // otherwise the new document would be considered as explicit (so flag would be cleared by the Document property assignment). 
            this.Document = document;

            // Values that must be set as a side effect of Document assignment,
            // that are required for the RichTextBox instance functioning. 
            Invariant.Assert(this.TextContainer != null);
            Invariant.Assert(this.TextEditor != null); 
            Invariant.Assert(this.TextEditor.TextContainer == this.TextContainer); 
        }
 
        #endregion Constructors

        // ------------------------------------------------------------
        // 
        // Public Methods
        // 
        // ----------------------------------------------------------- 

        #region Public Methods 

        // ------------------------------------------------------------
        //
        // IAddChild interface 
        //
        // ------------------------------------------------------------ 
 
        ///
        /// This method is called to Add the object as a child of the RichTextBox.  This method is used primarily 
        /// by the parser; a more direct way of adding a child to a RichTextBox is to use the 
        /// property.
        ///
        /// 
        /// The object to add as a child; it must be a UIElement.
        /// 
        void IAddChild.AddChild(Object value) 
        {
            if (value == null) 
            {
                throw new ArgumentNullException("value");
            }
 
            if (!(value is FlowDocument))
            { 
                throw new ArgumentException(SR.Get(SRID.UnexpectedParameterType, value.GetType(), typeof(FlowDocument)), "value"); 
            }
 
            if (!_implicitDocument)
            {
                throw new ArgumentException(SR.Get(SRID.CanOnlyHaveOneChild, this.GetType(), value.GetType()));
            } 

            this.Document = (FlowDocument)value; 
        } 

        /// 
        /// This method is called by the parser when text appears under the tag in markup.
        /// As RichTextBox do not support text, calling this method has no effect if the text
        /// is all whitespace.  For non-whitespace text, throw an exception.
        /// 
        ///
        /// Text to add as a child. 
        /// 
        void IAddChild.AddText(string text)
        { 
            if (text == null)
            {
                throw new ArgumentNullException("text");
            } 

            XamlSerializerUtil.ThrowIfNonWhiteSpaceInAddText(text, this); 
        } 

 
        ///
        /// Returns the TextPointer located closest to a supplied Point.
        /// 
        ///  
        /// Point to query, in the coordinate space of the RichTextBox.
        ///  
        ///  
        /// If true, this method will always return a TextPointer --
        /// the closest position as calculated by the control's heuristics. 
        /// If false, this method will return a null position if the test
        /// point does not fall within any character bounding box.
        /// 
        ///  
        /// The closest TextPointer to the supplied Point, or null if
        /// snapToText is false and the supplied Point is not contained 
        /// within any character bounding box, or if no content element yet exists. 
        /// 
        ///  
        /// Throws InvalidOperationException if layout is dirty.
        /// 
        public TextPointer GetPositionFromPoint(Point point, bool snapToText)
        { 
            if (this.RenderScope == null)
            { 
                return null; 
            }
 
            return (TextPointer)GetTextPositionFromPointInternal(point, snapToText);
        }

        ///  
        /// Returns the associated SpellingError at a specified position.
        ///  
        ///  
        /// Position of text to query.
        ///  
        /// 
        /// The position and its LogicalDirection specify a character to query.
        /// If the specificed character is not part of a misspelled word then
        /// this method will return null. 
        /// 
        public SpellingError GetSpellingError(TextPointer position) 
        { 
            ValidationHelper.VerifyPosition(this.TextContainer, position);
 
            return this.TextEditor.GetSpellingErrorAtPosition(position, position.LogicalDirection);
        }

        ///  
        /// Returns the TextRange covering a misspelled word at a specified
        /// position. 
        ///  
        /// 
        /// Position of text to query. 
        /// 
        /// 
        /// The position and its LogicalDirection specify a character to query.
        /// If the specificed character is not part of a misspelled word then 
        /// this method will return null.
        ///  
        public TextRange GetSpellingErrorRange(TextPointer position) 
        {
            ValidationHelper.VerifyPosition(this.TextContainer, position); 

            SpellingError spellingError = this.TextEditor.GetSpellingErrorAtPosition(position, position.LogicalDirection);

            return (spellingError == null) ? null : new TextRange(spellingError.Start, spellingError.End); 
        }
 
        ///  
        /// Returns the position of the next character in a specificed direction
        /// that is the start of a misspelled word. 
        /// 
        /// 
        /// Position of text to query.
        ///  
        /// 
        /// Direction to query. 
        ///  
        /// 
        /// The position and its LogicalDirection specify a character to query. 
        /// The search includes the spelling error containing the character
        /// specified by position/direction (if any).
        ///
        /// If no misspelled word is encountered, the method returns null. 
        /// 
        public TextPointer GetNextSpellingErrorPosition(TextPointer position, LogicalDirection direction) 
        { 
            ValidationHelper.VerifyPosition(this.TextContainer, position);
 
            return (TextPointer)this.TextEditor.GetNextSpellingErrorPosition(position, direction);
        }

        #endregion Public Methods 

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

        #region Protected Methods
 
        /// 
        /// Creates AutomationPeer () 
        ///  
        protected override AutomationPeer OnCreateAutomationPeer()
        { 
            return new RichTextBoxAutomationPeer(this);
        }

        ///  
        /// Measurement override. Implement your size-to-content logic here.
        ///  
        ///  
        /// Sizing constraint.
        ///  
        protected override Size MeasureOverride(Size constraint)
        {
            if (constraint.Width == Double.PositiveInfinity)
            { 
                // If we're sized to infinity, we won't behave the same way TextBox does under
                // the same conditions.  So, we fake it. 
                constraint.Width = this.MinWidth; 
            }
            return base.MeasureOverride(constraint); 
        }

        // Allocates the initial render scope for this control.
        internal override FrameworkElement CreateRenderScope() 
        {
            FlowDocumentView renderScope = new FlowDocumentView(); 
            renderScope.Document = this.Document; 

            // Set a margin so that the BiDi Or Italic caret has room to render at the edges of content. 
            // Otherwise, anti-aliasing or italic causes the caret to be partially clipped.
            renderScope.Document.PagePadding = new Thickness(CaretElement.CaretPaddingWidth, 0, CaretElement.CaretPaddingWidth, 0);

            // We want current style to ignore all properties from theme style for renderScope. 
            renderScope.OverridesDefaultStyle = true;
 
            return renderScope; 
        }
 
        #endregion Protected Methods

        // -----------------------------------------------------------
        // 
        // Public Properties
        // 
        // ----------------------------------------------------------- 

        #region Public Properties 

        /// 
        /// A Property representing a content of this RichTextBox
        ///  
        public FlowDocument Document
        { 
            get 
            {
                Invariant.Assert(_document != null); 
                return _document;
            }

            set 
            {
                if (value == null) 
                { 
                    throw new ArgumentNullException("value");
                } 

                if (value != _document &&
                    value.StructuralCache != null && value.StructuralCache.TextContainer != null &&
                    value.StructuralCache.TextContainer.TextSelection != null) 
                {
                    throw new ArgumentException(SR.Get(SRID.RichTextBox_DocumentBelongsToAnotherRichTextBoxAlready)); 
                } 

                if (_document != null && this.TextSelectionInternal.ChangeBlockLevel > 0) 
                {
                    throw new InvalidOperationException(SR.Get(SRID.RichTextBox_CantSetDocumentInsideChangeBlock));
                }
 
                if (value == _document)
                { 
                    // Same document nothing to do. 
                    return;
                } 

                // Identify the case for the _document initialization
                bool initialSetting = _document == null;
 
                // Detach existing FlowDocument
                if (_document != null) 
                { 
                    // Detach PageSize change listener
                    _document.PageSizeChanged -= new EventHandler(this.OnPageSizeChangedHandler); 

                    // Remove the document from the logical tree
                    this.RemoveLogicalChild(_document);
 
                    // Stop collecting text changes
                    _document.TextContainer.CollectTextChanges = false; 
 
                    // Clear thereference to a document
                    _document = null; 
                }

                // Clear the implicitDocument flag.
                // Any assignment to the Document property clears the _implicitDocument flag 
                // expect for the initial one, which may happen from a RichTextBox constructor which
                // can create an empolicit document and sets _implicitDocument flag before 
                // the Document property assignment. 
                if (!initialSetting)
                { 
                    _implicitDocument = false;
                }

                // Store the document for future use - just for comparing when it changes and detaching from it 
                _document = value;
 
                // Save existing renderScope before calling TextBoxBase.InitializeTextContainer, 
                // because it will discard it.
                UIElement renderScope = this.RenderScope; 

                // Start collecting text changes
                _document.TextContainer.CollectTextChanges = true;
 
                // Attach to new text container and re-create TextEditor instance
                this.InitializeTextContainer(_document.TextContainer); 
 
                // Add listener for PageSize - to redirect it to inner renderScope.Width
                _document.PageSizeChanged += new EventHandler(this.OnPageSizeChangedHandler); 

                // Add the document as a child to the logical tree
                this.AddLogicalChild(_document);
 
                // Re-attach to visual tree
                if (renderScope != null) 
                { 
                    // Re-atach to visual tree if we have a new TextContainer.
                    this.AttachToVisualTree(); 
                }

                // Make sure that all inherited properties properly transferred
                // to the new document according to its Standalone/Inherited status. 
                TransferInheritedPropertiesToFlowDocument();
 
                // Raise a TextChanged event for all assignments except initializing one. 
                if (!initialSetting)
                { 
                    Invariant.Assert(this.PendingUndoAction == UndoAction.None);
                    this.PendingUndoAction = UndoAction.Clear;
                    try
                    { 
                        this.OnTextChanged(new TextChangedEventArgs(TextChangedEvent, UndoAction.Clear));
                    } 
                    finally 
                    {
                        this.PendingUndoAction = UndoAction.None; 
                    }
                }
            }
        } 

        ///  
        /// This method is used by TypeDescriptor to determine if this property should 
        /// be serialized.
        ///  
        // According to the contract with the serializer the (private) method named as
        // ShouldSerialize tells the serializer whether it should serialize the
        // property for this instance or not.
        // We want to avoid serializing implicitly created document if it does not have any meaningful content. 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public bool ShouldSerializeDocument() 
        { 
            Block firstBlock = _document.Blocks.FirstBlock;
 
            if (_implicitDocument &&
                (firstBlock == null
                    ||
                    firstBlock == _document.Blocks.LastBlock && 
                    firstBlock is Paragraph))
            { 
                Inline firstInline = (firstBlock == null) ? null : ((Paragraph)firstBlock).Inlines.FirstInline; 
                if (firstInline == null
                        || 
                        firstInline == ((Paragraph)firstBlock).Inlines.LastInline &&
                        firstInline is Run &&
                        firstInline.ContentStart.CompareTo(firstInline.ContentEnd) == 0)
                { 
                    // We have implicit document without any text content.
                    return false; 
                } 
            }
 
            // In all other cases we should serialize the FlowDocument child.
            return true;
        }
 
        /// 
        /// Enables or disables TextElements and UIElements contained in this RichTextBox's FlowDocument. 
        ///  
        /// 
        /// By default child elements have their IsEnabled property coerced 
        /// false when hosted by RichTextBox.  Use this property to enable
        /// contained elements.
        /// 
        public static readonly DependencyProperty IsDocumentEnabledProperty = 
            DependencyProperty.Register("IsDocumentEnabled", typeof(bool), typeof(RichTextBox),
            new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnIsDocumentEnabledChanged))); 
 
        /// 
        /// Enables or disables TextElements and UIElements contained in this RichTextBox's FlowDocument. 
        /// 
        /// 
        /// 
        ///  
        public bool IsDocumentEnabled
        { 
            get 
            {
                return (bool)GetValue(IsDocumentEnabledProperty); 
            }

            set
            { 
                SetValue(IsDocumentEnabledProperty, value);
            } 
        } 

        // ........................................................... 
        //
        // Content Accessing Properties
        //
        // .......................................................... 

        #region Content Accessing Properties 
 
        /// 
        /// Returns enumerator to logical children 
        /// 
        protected internal override IEnumerator LogicalChildren
        {
            get 
            {
                if (this._document == null) 
                { 
                    // Using _document (not .Document),as it can be null on destruction scenarios
                    // (even though .Document cannot be null) - it is called for property invalidation reasons... 
                    return EmptyEnumerator.Instance;
                }
                else
                { 
                    return new SingleChildEnumerator(this._document);
                } 
            } 
        }
 
        /// 
        /// Text Selection (readonly)
        /// 
        public TextSelection Selection 
        {
            get 
            { 
                return (TextSelection)TextSelectionInternal;
            } 
        }

        /// 
        /// Position of the caret. 
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
        public TextPointer CaretPosition 
        {
            get 
            {
                return Selection.MovingPosition;
            }
 
            set
            { 
                if (value == null) 
                {
                    throw new ArgumentNullException("value"); 
                }
                if (!Selection.Start.IsInSameDocument(value))
                {
                    throw new ArgumentException(SR.Get(SRID.RichTextBox_PointerNotInSameDocument), "value"); 
                }
                Selection.SetCaretToPosition(value, value.LogicalDirection, /*allowStopAtLineEnd:*/true, /*allowStopNearSpace:*/false); 
            } 
        }
 
        #endregion Content Accessing Properties

        #endregion Public Properties
 
        //-----------------------------------------------------
        // 
        //  Internal Methods 
        //
        //------------------------------------------------------ 

        #region Internal Methods

        // 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;
            }
        }
 
        #endregion Internal Methods
 
        // ----------------------------------------------------------- 
        //
        // Private Methods 
        //
        // ------------------------------------------------------------

        #region Private Methods 

        // ........................................................... 
        // 
        // Transferring Properties from RichTextBox down to FlowDocument
        // 
        // ...........................................................

        // We need to transfer all character formatting properties from RichTextBox level into its FlowDocument.
        // 
        // Note that we have to set all properties explicitly - not even trying
        // to bypass some of them when using assumptions about their default values (for non-implicit document) 
        // or a coincidence with the current context values (for implicit document) - 
        // the FlowDocument mast have all properties explicitly set to keep them intact
        // after being moved to another contextual location (both in Save-Load and in Print scenarios). 

        // For this purpose we set listeners for all these properties:
        private static void HookupInheritablePropertyListeners()
        { 
            // All inhgeriting formatting properties need to be transferred over the implicit document boundary.
            // This is required for treating UIContext as default setting for implicit document. 
            // Note that mechanism is not applied to explicit document. 
            PropertyChangedCallback formattingPropertyCallback = new PropertyChangedCallback(OnFormattingPropertyChanged);
            DependencyProperty[] inheritableFormattingProperties = TextSchema.GetInheritableProperties(typeof(FlowDocument)); 
            for (int i = 0; i < inheritableFormattingProperties.Length; i++)
            {
                inheritableFormattingProperties[i].OverrideMetadata(typeof(RichTextBox), new FrameworkPropertyMetadata(formattingPropertyCallback));
            } 

            // Inheriting behavioral properties need to be transferred over any Standalone document boundary. 
            PropertyChangedCallback behavioralPropertyCallback = new PropertyChangedCallback(OnBehavioralPropertyChanged); 
            DependencyProperty[] inheritableBehavioralProperties = TextSchema.BehavioralProperties;
            for (int i = 0; i < inheritableBehavioralProperties.Length; i++) 
            {
                inheritableBehavioralProperties[i].OverrideMetadata(typeof(RichTextBox), new FrameworkPropertyMetadata(behavioralPropertyCallback));
            }
        } 

        // Transfer all properties from the current context to this 
        // implicit document - to simulate inheritance. 
        // This is how implicit document gets its initial values -
        // from the context. 
        // After that RichTextBox will maintain such inheritance simulation
        // (for implicit document only) by listening for property
        // change notifications.
        private void TransferInheritedPropertiesToFlowDocument() 
        {
            // Implicit document needs all formatting properties be transferred to it 
            if (_implicitDocument) 
            {
                DependencyProperty[] inheritableFormattingProperties = TextSchema.GetInheritableProperties(typeof(FlowDocument)); 
                for (int i = 0; i < inheritableFormattingProperties.Length; i++)
                {
                    DependencyProperty property = inheritableFormattingProperties[i];
                    TransferFormattingProperty(property, this.GetValue(property)); 
                }
            } 
 
            // Behavioral properties must be transferred to any document whether it has Standalone
            // or Inherited FormattingDefaults. All such values are set as local values even 
            // in case when they are equal to the ones inherited from the UI context
            // (see TransferBehavioralProperty method implementation).
            // Such strong logic is needed to work correctly in any sequence of
            // setting FormattingDefaults property and adding children. 
            DependencyProperty[] inheritableBehavioralProperties = TextSchema.BehavioralProperties;
            for (int i = 0; i < inheritableBehavioralProperties.Length; i++) 
            { 
                DependencyProperty property = inheritableBehavioralProperties[i];
                TransferBehavioralProperty(property, this.GetValue(property)); 
            }
        }

        ///  
        /// Callback for changes to the any text formatting property.
        /// Transfers the new value to explisit setting on a FlowDocument. 
        ///  
        private static void OnFormattingPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        { 
            RichTextBox richTextBox = (RichTextBox)d;

            if (richTextBox._implicitDocument)
            { 
                richTextBox.TransferFormattingProperty(e.Property, e.NewValue);
            } 
        } 

        // Transfers single formatting property from this RichTextBox to its implicit document 
        private void TransferFormattingProperty(DependencyProperty property, object inheritedValue)
        {
            Invariant.Assert(_implicitDocument, "We only supposed to do this for implicit documents");
 
            object defaultValue = _document.GetValue(property);
            if (!TextSchema.ValuesAreEqual(inheritedValue, defaultValue)) 
            { 
                _document.ClearValue(property);
                defaultValue = _document.GetValue(property); 
                if (!TextSchema.ValuesAreEqual(inheritedValue, defaultValue))
                {
                    _document.SetValue(property, inheritedValue);
                } 
            }
        } 
 
        /// 
        /// Callback for changes to the any behavioral property. 
        /// Transfers the new value to a FlowDocument.
        /// 
        /// 
        /// Behavioral properties must be transferred to any document whether it has Standalone 
        /// or Inherited FormattingDefaults. All such values are set as local values even
        /// in case when they are equal to the ones inherited from the UI context. 
        /// Such strong logic is needed to work correctly in any sequence of 
        /// setting FormattingDefaults property and adding children.
        ///  
        private static void OnBehavioralPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            RichTextBox richTextBox = (RichTextBox)d;
 
            richTextBox.TransferBehavioralProperty(e.Property, e.NewValue);
        } 
 
        /// 
        /// Transfers single behavioral property from this RichTextBox to its implicit document 
        /// 
        /// 
        /// Behavioral properties must be transferred to any document whether it has Standalone
        /// or Inherited FormattingDefaults. All such values are set as local values even 
        /// in case when they are equal to the ones inherited from the UI context.
        /// Such strong logic is needed to work correctly in any sequence of 
        /// setting FormattingDefaults property and adding children. 
        /// 
        private void TransferBehavioralProperty(DependencyProperty property, object inheritedValue) 
        {
            // Set the value unconditionally as explicit local value
            _document.SetValue(property, inheritedValue);
        } 

        // ........................................................... 
        // 
        // TextEditor Parameterization Properties Access
        // 
        // ...........................................................

        #region TextEditor Parameterization Propeties Access
 
        private void OnPageSizeChangedHandler(object sender, EventArgs e)
        { 
            if (this.RenderScope == null) 
            {
                return; 
            }

            // Make sure that the TextWrapping property is set correctly
            if (this.Document != null) 
            {
                this.Document.TextWrapping = TextWrapping.Wrap; 
            } 

            // The Document does not have explicit PageWidth set OR Wrap/WrapWithOverflow is requested. 
            // The RenderScope must occupy as much space as its content required (no wrapping)
            // We could set Width to positive infinity, but that would make horizontal scrollbar
            // look wrong. So we need to make sure that render scope has a size of
            // its actual content. For that we clear loal value of Width property 
            // from RenderScope.
 
            // To let RenderScope occupy all space we clear Width local value on it. 
            this.RenderScope.ClearValue(FlowDocumentView.WidthProperty);
 
            // Set alighment to Stretch - for RenderScope to occupy the whole viewport.
            this.RenderScope.ClearValue(FrameworkElement.HorizontalAlignmentProperty);
            // Normally TextBox style does not set any balue for HorizontalAlignment property,
            // so clearing would set it to a required default - Stretch. 
            // However, if style author sets some other value - it will be set as a result of ClearValue,
            // so we need to enforce that. 
            // Note, that trying to clear first saves a memory for inline property application. 
            if (this.RenderScope.HorizontalAlignment != HorizontalAlignment.Stretch)
            { 
                this.RenderScope.HorizontalAlignment = HorizontalAlignment.Stretch;
            }
        }
 

        #endregion TextEditor Parameterization Properties Access 
 
        // Callback for IsDocumentEnabledProperty changes.
        // Forces a coercion of the child FlowDocument, with the new setting. 
        private static void OnIsDocumentEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            RichTextBox richTextBox = (RichTextBox)d;
 
            if (richTextBox.Document != null)
            { 
                richTextBox.Document.CoerceValue(IsEnabledProperty); 
            }
        } 

        #endregion Private Methods

        // ------------------------------------------------------------ 
        //
        // Private Fields 
        // 
        // -----------------------------------------------------------
 
        #region Private Fields

        private FlowDocument _document;
        private bool _implicitDocument; // true if Document property was set by AddChild or Document setter (not in constructor) 

        private static DependencyObjectType _dType; // Needed for property system optimization 
 
        #endregion Private Fields
    } 
}

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