In an application I’m currently writing my users will be creating many text notes and I wanted to allow for the user to create nicely formatted documents, as well as having the ability for fine-grained control over printing options. Enter the RichTextBox – it is similar to a TextBox, but provides more advanced text formatting options to the user. Enabling the advanced editing features is trivial (read up on the available Editing Commands), literally in minutes you can create a WYSIWYG editor. Where things get sticky is when you start talking about databinding.
The RichTextBox stores the text in its Document property which is of type FlowDocument. It isn’t a dependency property, nor does it implement INotiftyPropertyChanged so you can’t bind directly to it. This is a problem. In my application I want my users to create richly formatted documents which are added to a Notes collection on my entity and then have each note persisted as a string in my database.
I decided the best way to go would be to subclass the RichTextBox, and expose a DependencyProperty to handle the binding. I’d then need some plumbing internally to keep things in sync. Before I plunged headfirst into my own implementation, I spent a little time on Google to see how others have approached the problem. I found many people hoping to do the same thing I was, but not any complete solutions. I did find a MSDN forum post which had a code snippet that looked like a good place to start, and I also found some sample code for a WYSIWYG editor, so I cobbled the 2 together in my new WPFControls project and I was off and running.
Getting the Two-Way databinding working did turn out to be more of a chore than I’d hoped, but using the IValueConverter interface I was eventually able to bind a string property on a domain entity to the Document property on a RichTextBox. I decided to wrap the implementation up in its own UserControl for reuse, so in the end my domain entity is bound to a string DP on the UC, and the Document property on the RichTextBox is bound to this same string property on the UC using IValueConverter.
To use the control in a project you first need to reference it in your project, and then in xaml you can reference it like this:
and then to use it:
I added a couple of properties on the control itself to illustrate that it easy to still have control over the inner wrapped RTB. You can see in my sample above I have it bound to a ListBox control which has a list of Notes. The Description property is the string holding the xaml of the FlowDocument.
I have included a rough sample project you can use to create your own control for your projects. Enjoy!BlueTango.WPFControls.zip (3100)
UPDATE: A reader contributed this code a while back…
From Abbott Fleur and Dan Vanderboom: “I’m expanding your BindableRichTextBox control to allow linq-sql binding to db text source. I’m planning on using an existing routine I’ve written that loads the RTB based on the ip format and saves based on a SaveAs (DataFormats) property. ”
While I have not tried this code myself – here it is. Thanks Abbott and Dan!BoundRichTextBox.zip (2385)
While comments are welcome, please note that I am unable to offer help or support for using this update or the original code. It is provided “as-is” without warranty or guarantees.