/************************************************************************************* Extended WPF Toolkit Copyright (C) 2007-2013 Xceed Software Inc. This program is provided to you under the terms of the Microsoft Public License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license For more features, controls, and fast professional support, pick up the Plus Edition at http://xceed.com/wpf_toolkit Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids ***********************************************************************************/ using System; using System.Windows; using System.Windows.Data; using System.Windows.Threading; namespace Xceed.Wpf.Toolkit { public class RichTextBox : System.Windows.Controls.RichTextBox { #region Private Members private bool _preventDocumentUpdate; private bool _preventTextUpdate; #endregion //Private Members #region Constructors public RichTextBox() { } public RichTextBox( System.Windows.Documents.FlowDocument document ) : base( document ) { } #endregion //Constructors #region Properties #region Text public static readonly DependencyProperty TextProperty = DependencyProperty.Register( "Text", typeof( string ), typeof( RichTextBox ), new FrameworkPropertyMetadata( String.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnTextPropertyChanged, CoerceTextProperty, true, UpdateSourceTrigger.LostFocus ) ); public string Text { get { return ( string )GetValue( TextProperty ); } set { SetValue( TextProperty, value ); } } private static void OnTextPropertyChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( RichTextBox )d ).UpdateDocumentFromText(); } private static object CoerceTextProperty( DependencyObject d, object value ) { return value ?? ""; } #endregion //Text #region TextFormatter public static readonly DependencyProperty TextFormatterProperty = DependencyProperty.Register( "TextFormatter", typeof( ITextFormatter ), typeof( RichTextBox ), new FrameworkPropertyMetadata( new RtfFormatter(), OnTextFormatterPropertyChanged ) ); public ITextFormatter TextFormatter { get { return ( ITextFormatter )GetValue( TextFormatterProperty ); } set { SetValue( TextFormatterProperty, value ); } } private static void OnTextFormatterPropertyChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { RichTextBox richTextBox = d as RichTextBox; if( richTextBox != null ) richTextBox.OnTextFormatterPropertyChanged( ( ITextFormatter )e.OldValue, ( ITextFormatter )e.NewValue ); } protected virtual void OnTextFormatterPropertyChanged( ITextFormatter oldValue, ITextFormatter newValue ) { this.UpdateTextFromDocument(); } #endregion //TextFormatter #endregion //Properties #region Methods protected override void OnTextChanged( System.Windows.Controls.TextChangedEventArgs e ) { base.OnTextChanged( e ); UpdateTextFromDocument(); } private void UpdateTextFromDocument() { if( _preventTextUpdate ) return; _preventDocumentUpdate = true; Text = TextFormatter.GetText( Document ); _preventDocumentUpdate = false; } private void UpdateDocumentFromText() { if( _preventDocumentUpdate ) return; _preventTextUpdate = true; TextFormatter.SetText( Document, Text ); _preventTextUpdate = false; } /// /// Clears the content of the RichTextBox. /// public void Clear() { Document.Blocks.Clear(); } public override void BeginInit() { base.BeginInit(); // Do not update anything while initializing. See EndInit _preventTextUpdate = true; _preventDocumentUpdate = true; } public override void EndInit() { base.EndInit(); _preventTextUpdate = false; _preventDocumentUpdate = false; // Possible conflict here if the user specifies // the document AND the text at the same time // in XAML. Text has priority. if( !string.IsNullOrEmpty( Text ) ) UpdateDocumentFromText(); else UpdateTextFromDocument(); } #endregion //Methods } }