he RichTextBox component in WPF/.NET 3.0 received a major upgrade compared to the previous version of the RichTextBox control that shipped with.NET 2.0. But with the expanded capability comes the need for additional APIs and different usage patterns. This article explores some of the advanced features of the WPF RichTextBox from both a XAML-based design standpoint, and explores how to work with it using C# code.
You add a RichTextBox to your form using the XAML code:
<RichTextBox x:Name="XAMLRichBox" SpellCheck.IsEnabled="True"
attribute simply gives you a reference to work with that you'll use later to bind commands to the RichTextBox. MinHeight
constrains the minimum size the component will render which is important, because by default renders as a single linewhich won't look right for a sophisticated editing control.
Similar to previous versions of the RichTextBox control, this one supports a wide variety of formatting as shown in Figure 1
. And if you have worked with the RichTextBox in .NET 2.0 or even the Windows SDK, you'll be glad to see the new SpellCheck.IsEnabled
attribute. Yes, the RichTextBox not only supports spell checking in WPF, but provides UI support via snazzy inline red squiggles and suggests alternative spellingsjust like Microsoft Word (see Figure 2
|Figure 1. Good Formatting Support: The figure shows some of the text formatting that the RichTextBox supports, such as underlining, italic, and bold text, as well as advanced features such as spell checking.||
|Figure 2. RichTextBox Spell Checking: Just like Microsoft Word, the RichTextBox underlines misspelled text and provides a popup window that offers alternative spellings.||
Unfortunately, just adding the RichTextBox to your form doesn't give you what you might expect in terms of toolbar buttons to apply bold or italic type, etc. Instead, you'll need to roll your own UI and hook into the RichTextBox's Command interface. The upside of the roll your own approach is that it gives you absolute control over the way your interface works. The downside, of course, is that you have to do all the work yourself.
The Command Interface
Microsoft intended developers to work with the RichTextBox component via a Command interface. Although the concept here isn't new to most folks who have been developing GUIs, the actual implementation and syntax is a little different in XAML-land.
You'll need to add a ToolBar component (optional but recommended) and some ToggleButton components that set up the binding to your rich text box. The Command
attribute on each of these components defines the functionality you want to activate on the RichTextBox, while the CommandTarget
defines which RichTextBox you want these buttons to target. Here's an example that adds a ToolBar and three ToggleButtons:
Although the code example included with this article includes only a few command buttons, there are a total of 47 different commands available to choose from. You can see them by checking the EditingCommands
class, which behaves just like an enumeration, with IntelliSense. Obviously, from a user-interface standpoint you'll want to keep the list of commands you support as small as possible while still meeting the needs of your users and the application you're developing. Presenting the user with 47 icons above a 4-line RichTextBox has some clearly negative implications from a usability standpoint.
Even if you don't explicitly add bindings to any of the command objects, keyboard shortcuts such as Ctrl-B
for bold are still enabled by default. You can disable any of the default enabled commands by adding a CommandBinding
. In the snippet below, the attribute CanExecute
references an event handler that can incorporate logic to prevent the command from executing:
The corresponding event handler in the C# code-behind file sets two properties on the event object. Setting CanExecute
lets components that are bound to the event know that this option is not currently available. In this case, to block the ToggleBold command, setting CanExecute
disables the Bold button in the toolbar appear disabled. The second property, Handled
, prevents the ToggleBold
command from being routed to the RichTextBox:
protected void BlockTheCommand(object sender,
e.CanExecute = false;
e.Handled = true;
If you choose to incorporate complex logic in your CanExecute
handlers, keep in mind that this event gets fired often, because the UI constantly checks and re-checks to see if the command is available. If you need to access resources such as a database or a Web service to determine if the command should be available, make sure you cache the resource and check it only periodically, or it will destroy your performance.