You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
4.1 KiB
135 lines
4.1 KiB
using System;
|
|
using System.Windows;
|
|
using System.Windows.Data;
|
|
using System.Windows.Threading;
|
|
|
|
namespace Microsoft.Windows.Controls
|
|
{
|
|
public class RichTextBox : System.Windows.Controls.RichTextBox
|
|
{
|
|
#region Private Members
|
|
|
|
private bool _textHasLoaded;
|
|
private bool isInvokePending;
|
|
|
|
#endregion //Private Members
|
|
|
|
#region Constructors
|
|
|
|
public RichTextBox()
|
|
{
|
|
Loaded += RichTextBox_Loaded;
|
|
}
|
|
|
|
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 rtb = (RichTextBox)d;
|
|
|
|
if (!rtb._textHasLoaded)
|
|
{
|
|
rtb.TextFormatter.SetText(rtb.Document, (string)e.NewValue);
|
|
rtb._textHasLoaded = true;
|
|
}
|
|
}
|
|
|
|
private static object CoerceTextProperty(DependencyObject d, object value)
|
|
{
|
|
return value ?? "";
|
|
}
|
|
|
|
#endregion //Text
|
|
|
|
#region TextFormatter
|
|
|
|
private ITextFormatter _textFormatter;
|
|
/// <summary>
|
|
/// The ITextFormatter the is used to format the text of the RichTextBox.
|
|
/// Deafult formatter is the RtfFormatter
|
|
/// </summary>
|
|
public ITextFormatter TextFormatter
|
|
{
|
|
get
|
|
{
|
|
if (_textFormatter == null)
|
|
_textFormatter = new RtfFormatter(); //default is rtf
|
|
|
|
return _textFormatter;
|
|
}
|
|
set
|
|
{
|
|
_textFormatter = value;
|
|
}
|
|
}
|
|
|
|
#endregion //TextFormatter
|
|
|
|
#endregion //Properties
|
|
|
|
#region Methods
|
|
|
|
private void InvokeUpdateText()
|
|
{
|
|
if (!isInvokePending)
|
|
{
|
|
Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(UpdateText));
|
|
isInvokePending = true;
|
|
}
|
|
}
|
|
|
|
private void UpdateText()
|
|
{
|
|
//when the Text is null and the Text hasn't been loaded, it indicates that the OnTextPropertyChanged event hasn't exceuted
|
|
//and since we are initializing the text from here, we don't want the OnTextPropertyChanged to execute, so set the loaded flag to true.
|
|
//this prevents the cursor to jumping to the front of the textbox after the first letter is typed.
|
|
if (!_textHasLoaded && string.IsNullOrEmpty(Text))
|
|
_textHasLoaded = true;
|
|
|
|
if (_textHasLoaded)
|
|
Text = TextFormatter.GetText(Document);
|
|
|
|
isInvokePending = false;
|
|
}
|
|
|
|
#endregion //Methods
|
|
|
|
#region Event Hanlders
|
|
|
|
private void RichTextBox_Loaded(object sender, RoutedEventArgs e)
|
|
{
|
|
Binding binding = BindingOperations.GetBinding(this, TextProperty);
|
|
|
|
if (binding != null)
|
|
{
|
|
if (binding.UpdateSourceTrigger == UpdateSourceTrigger.Default || binding.UpdateSourceTrigger == UpdateSourceTrigger.LostFocus)
|
|
{
|
|
PreviewLostKeyboardFocus += (o, ea) => UpdateText(); //do this synchronously
|
|
}
|
|
else
|
|
{
|
|
TextChanged += (o, ea) => InvokeUpdateText(); //do this async
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion //Event Hanlders
|
|
}
|
|
}
|
|
|