diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/Formatters/ITextFormatter.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/Formatters/ITextFormatter.cs new file mode 100644 index 00000000..f8e22d41 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/Formatters/ITextFormatter.cs @@ -0,0 +1,11 @@ +using System; +using System.Windows.Documents; + +namespace Microsoft.Windows.Controls +{ + public interface ITextFormatter + { + string GetText(FlowDocument document); + void SetText(FlowDocument document, string text); + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/Formatters/PlainTextFormatter.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/Formatters/PlainTextFormatter.cs new file mode 100644 index 00000000..1c792a32 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/Formatters/PlainTextFormatter.cs @@ -0,0 +1,21 @@ +using System; +using System.Windows.Documents; + +namespace Microsoft.Windows.Controls +{ + /// + /// Formats the RichTextBox text as plain text + /// + public class PlainTextFormatter : ITextFormatter + { + public string GetText(FlowDocument document) + { + return new TextRange(document.ContentStart, document.ContentEnd).Text; + } + + public void SetText(FlowDocument document, string text) + { + new TextRange(document.ContentStart, document.ContentEnd).Text = text; + } + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/Formatters/RtfFormatter.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/Formatters/RtfFormatter.cs new file mode 100644 index 00000000..e5a1def6 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/Formatters/RtfFormatter.cs @@ -0,0 +1,33 @@ +using System; +using System.Text; +using System.Windows.Documents; +using System.IO; +using System.Windows; + +namespace Microsoft.Windows.Controls +{ + /// + /// Formats the RichTextBox text as RTF + /// + public class RtfFormatter : ITextFormatter + { + public string GetText(FlowDocument document) + { + TextRange tr = new TextRange(document.ContentStart, document.ContentEnd); + using (MemoryStream ms = new MemoryStream()) + { + tr.Save(ms, DataFormats.Rtf); + return ASCIIEncoding.Default.GetString(ms.ToArray()); + } + } + + public void SetText(FlowDocument document, string text) + { + TextRange tr = new TextRange(document.ContentStart, document.ContentEnd); + using (MemoryStream ms = new MemoryStream(Encoding.ASCII.GetBytes(text))) + { + tr.Load(ms, DataFormats.Rtf); + } + } + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/Formatters/XamlFormatter.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/Formatters/XamlFormatter.cs new file mode 100644 index 00000000..07e1d31a --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/Formatters/XamlFormatter.cs @@ -0,0 +1,40 @@ +using System; +using System.Text; +using System.IO; +using System.Windows.Documents; +using System.Windows; + +namespace Microsoft.Windows.Controls +{ + /// + /// Formats the RichTextBox text as Xaml + /// + public class XamlFormatter : ITextFormatter + { + public string GetText(System.Windows.Documents.FlowDocument document) + { + TextRange tr = new TextRange(document.ContentStart, document.ContentEnd); + using (MemoryStream ms = new MemoryStream()) + { + tr.Save(ms, DataFormats.Xaml); + return ASCIIEncoding.Default.GetString(ms.ToArray()); + } + } + + public void SetText(System.Windows.Documents.FlowDocument document, string text) + { + try + { + TextRange tr = new TextRange(document.ContentStart, document.ContentEnd); + using (MemoryStream ms = new MemoryStream(Encoding.ASCII.GetBytes(text))) + { + tr.Load(ms, DataFormats.Xaml); + } + } + catch + { + throw new InvalidDataException("data provided is not in the correct Xaml format."); + } + } + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/RichTextBox.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/RichTextBox.cs new file mode 100644 index 00000000..4362c096 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/RichTextBox.cs @@ -0,0 +1,115 @@ +using System; +using System.Windows; +using System.Windows.Data; + +namespace Microsoft.Windows.Controls +{ + public class RichTextBox : System.Windows.Controls.RichTextBox + { + #region Private Members + + private bool _textHasLoaded; + + #endregion //Private Members + + #region Constructors + + public RichTextBox() + { + Loaded += RichTextBox_Loaded; + } + + public RichTextBox(System.Windows.Documents.FlowDocument document) + : base(document) + { + + } + + #endregion //Constructors + + #region Properties + + private ITextFormatter _textFormatter; + /// + /// The ITextFormatter the is used to format the text of the RichTextBox. + /// Deafult formatter is the RtfFormatter + /// + public ITextFormatter TextFormatter + { + get + { + if (_textFormatter == null) + _textFormatter = new RtfFormatter(); //default is rtf + + return _textFormatter; + } + set + { + _textFormatter = value; + } + } + + #region Text + + public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(RichTextBox), new FrameworkPropertyMetadata(String.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnTextPropertyChanged), new CoerceValueCallback(CoerceTextProperty), true, System.Windows.Data.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 + + #endregion //Properties + + #region Methods + + 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); + } + + #endregion //Methods + + #region Event Hanlders + + private void RichTextBox_Loaded(object sender, RoutedEventArgs e) + { + Binding binding = BindingOperations.GetBinding(this, TextProperty); + + if (binding.UpdateSourceTrigger == UpdateSourceTrigger.Default || binding.UpdateSourceTrigger == UpdateSourceTrigger.LostFocus) + { + LostFocus += (o, ea) => UpdateText(); + } + else + { + TextChanged += (o, ea) => UpdateText(); + } + } + + #endregion //Event Hanlders + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj index 915333ff..fac27c96 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj @@ -89,6 +89,11 @@ True + + + + +