Richtextbox wpf binding
There is a much easier way!
You can easily create an attached DocumentXaml
(or DocumentRTF
) property which will allow you to bind the RichTextBox
's document. It is used like this, where Autobiography
is a string property in your data model:
<TextBox Text="{Binding FirstName}" />
<TextBox Text="{Binding LastName}" />
<RichTextBox local:RichTextBoxHelper.DocumentXaml="{Binding Autobiography}" />
Voila! Fully bindable RichTextBox
data!
The implementation of this property is quite simple: When the property is set, load the XAML (or RTF) into a new FlowDocument
. When the FlowDocument
changes, update the property value.
This code should do the trick:
using System.IO;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
public class RichTextBoxHelper : DependencyObject
{
public static string GetDocumentXaml(DependencyObject obj)
{
return (string)obj.GetValue(DocumentXamlProperty);
}
public static void SetDocumentXaml(DependencyObject obj, string value)
{
obj.SetValue(DocumentXamlProperty, value);
}
public static readonly DependencyProperty DocumentXamlProperty =
DependencyProperty.RegisterAttached(
"DocumentXaml",
typeof(string),
typeof(RichTextBoxHelper),
new FrameworkPropertyMetadata
{
BindsTwoWayByDefault = true,
PropertyChangedCallback = (obj, e) =>
{
var richTextBox = (RichTextBox)obj;
// Parse the XAML to a document (or use XamlReader.Parse())
var xaml = GetDocumentXaml(richTextBox);
var doc = new FlowDocument();
var range = new TextRange(doc.ContentStart, doc.ContentEnd);
range.Load(new MemoryStream(Encoding.UTF8.GetBytes(xaml)),
DataFormats.Xaml);
// Set the document
richTextBox.Document = doc;
// When the document changes update the source
range.Changed += (obj2, e2) =>
{
if (richTextBox.Document == doc)
{
MemoryStream buffer = new MemoryStream();
range.Save(buffer, DataFormats.Xaml);
SetDocumentXaml(richTextBox,
Encoding.UTF8.GetString(buffer.ToArray()));
}
};
}
});
}
The same code could be used for TextFormats.RTF or TextFormats.XamlPackage. For XamlPackage you would have a property of type byte[]
instead of string
.
The XamlPackage format has several advantages over plain XAML, especially the ability to include resources such as images, and it is more flexible and easier to work with than RTF.
It is hard to believe this question sat for 15 months without anyone pointing out the easy way to do this.
Binding RichTextBox to a string
You can use RichTextBox
(link) from Extended WPF Toolkit.
Example:
<toolkit:RichTextBox x:Name="_richTextBox" Grid.Row="1" Margin="10" BorderBrush="Gray" Padding="10"
Text="{Binding Notes}"
ScrollViewer.VerticalScrollBarVisibility="Auto" />
where toolkit
is namespace to Extended WPF Toolkit library:
xmlns:toolkit="http://schemas.xceed.com/wpf/xaml/toolkit"
Installation guide:
Instructions for using the Extended WPF Toolkit binaries (link):
- Install .NET Framework 4.0 or 4.5
- Download the ExtendedWPFToolkit_Binaries
- Right-click ExtendedWPFToolkit_Binaries.zip -> Properties -> Unblock
- Unzip the ExtendedWPFToolkit_Binaries.zip
- Add a using statement ("using Xceed.Wpf.Toolkit;") to the top of .cs files
- Add a new xmlns (for example, xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit") to the top of XAML files
- In your XAML, use the namespace prefix (in the above example, )
Or you can install this library by NuGet (link):
PM> Install-Package Extended.Wpf.Toolkit
Wpf Richtextbox data binding issue: can't get the correct data
Sarina, there is no direct way to bind string variable to RichTextbox. You can find lots of problem statement for the same while searching on google. PreviewKeyDown show current key only so it may not show what was the previous text was.
Simple way
to set RichTextBox text:
Richtextbox.Document.Blocks.Clear();
Richtextbox.Document.Blocks.Add(new Paragraph(new Run("Text")));
to get RichTextBox text:
string richText = new TextRange(Richtextbox.Document.ContentStart, Richtextbox.Document.ContentEnd).Text;
You can use above methods with tricks and get the output you want. You can manually update your model in PreviewKeyDown event.
OR
There are only one permanent solution of this problem is to use attached property where you can put you login to get the text of the RichTextBox. It will help you to get and set you values easily.
This is the basic code for Text property for RichTextBox. You can modify it as per your need as I am not able to write exact you need. But it will surely help you to achieve your need.
public class RichTextBoxHelper
{
/// <summary>
/// Text Attached Dependency Property
/// </summary>
public static readonly DependencyProperty TextProperty =
DependencyProperty.RegisterAttached("Text", typeof(string), typeof(RichTextBoxHelper),
new FrameworkPropertyMetadata((string)null,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault |
FrameworkPropertyMetadataOptions.Journal,
new PropertyChangedCallback(OnTextChanged),
new CoerceValueCallback(CoerceText),
true,
UpdateSourceTrigger.PropertyChanged));
/// <summary>
/// Gets the Text property.
/// </summary>
public static string GetText(DependencyObject d)
{
return (string)d.GetValue(TextProperty);
}
/// <summary>
/// Sets the Text property.
/// </summary>
public static void SetText(DependencyObject d, string value)
{
d.SetValue(TextProperty, value);
}
/// <summary>
/// Returns the Text from a FlowDocument
/// </summary>
/// <param name="document">The document to get the text from</param>
/// <returns>Returns a string with the text of the flow document</returns>
public static string GetText(FlowDocument document)
{
return new TextRange(document.ContentStart, document.ContentEnd).Text;
}
/// <summary>
/// Handles changes to the Text property.
/// </summary>
private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
RichTextBox textBox = (RichTextBox)d;
if (e.NewValue != null)
{
textBox.Document.Blocks.Clear();
textBox.Document.Blocks.Add(new Paragraph(new Run(e.NewValue.ToString())));
}
}
}
XAML Binding
<RichTextBox Grid.Row="4" Width="200" Height="60" AcceptsReturn="True" AcceptsTab="True" VerticalScrollBarVisibility="Auto" PreviewKeyDown="PreviewKeyDown" local:RichTextBoxHelper.Text="{Binding DisplayText}">
</RichTextBox>
Bind the text of RichTextBox from Xaml
There is no built in way to do that. You can create Text attached property and bind to it like discussed here
Binding the selected text of a RichTextBox to a property in the ViewModel
You could use a Behavior
:
public class RichTextSelectionBehavior : Behavior<RichTextBox>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.SelectionChanged += RichTextBoxSelectionChanged;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.SelectionChanged -= RichTextBoxSelectionChanged;
}
void RichTextBoxSelectionChanged(object sender, System.Windows.RoutedEventArgs e)
{
SelectedText = AssociatedObject.Selection.Text;
}
public string SelectedText
{
get { return (string)GetValue(SelectedTextProperty); }
set { SetValue(SelectedTextProperty, value); }
}
public static readonly DependencyProperty SelectedTextProperty =
DependencyProperty.Register(
"SelectedText",
typeof(string),
typeof(RichTextSelectionBehavior),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSelectedTextChanged));
private static void OnSelectedTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var behavior = d as RichTextSelectionBehavior;
if (behavior == null)
return;
behavior.AssociatedObject.Selection.Text = behavior.SelectedText;
}
}
XAML usage:
<RichTextBox>
<i:Interaction.Behaviors>
<local:RichTextSelectionBehavior SelectedText="{Binding SelectedText}" />
</i:Interaction.Behaviors>
</RichTextBox>
(where SelectedText
is a string property on your ViewModel)
Related Topics
Use Multiple Jwt Bearer Authentication
Opensubkey() Returns Null for a Registry Key That I Can See in Regedit.Exe
Difference Between Events and Delegates and Its Respective Applications
Do You Have to Put Task.Run in a Method to Make It Async
Change Attribute's Parameter at Runtime
Insert/Update Many to Many Entity Framework . How to Do It
How to Parse JSON Without JSON.Net Library
How to "Steal" an Event Handler from One Control and Give It to Another
How to Update Record Using Entity Framework 6
Type or Namespace Name Does Not Exist
How to Decode a Url Parameter Using C#
Get Mime Type from Filename Extension
.Net Out of Memory Exception - Used 1.3Gb But Have 16Gb Installed