WPF RichTextBoxToolBar Control






4.94/5 (10 votes)
Developing an easy to use toolbar for formatting the contents of a RichTextBox WPF control.
Introduction
The representation of text is undoubtedly one of the more important UI features. However, sometimes
we need more than to display a simple text.
The FlowDocuments
class provides such possibilities.
The component is a container of XAML elements which allow to mark up documents like HTML.
To edit such text having complex markup, we use the RichTextBox
editor. The editor is very useful, but it has several shortcomings, for example:
- It outputs its content as a
FlowDocument
, rather than as an XAML markup, that is not very convenient for implementing data-binding. - Has poor compatibility with other text editors like Microsoft Word or WordPad.
- To add the ability to scale the content you have much work, but in total, it will not work correctly.
- Not all commands are implemented in the form of commands, such as
EditingCommands
,ApplicationCommands
, and others. - There is no multi-language spelling support.
- It doesn't have a built-in formatting toolbar, which means additional work to set up the control in a host application.
These drawbacks become apparent and to eliminate them, we require to expend a significant amount of time when developing applications. However, the list is not complete because the editor has many other shortcomings and so the component requires careful debugging and error correction. For example, if you copy from a Microsoft Word text having subscript and superscript characters, it does not handle them correctly although text is shown as expected. And when you try to copy the text back into Word, formatting is lost.
The solution of one of the problems shown above is related with creating an easy-to-use toolbar for
the RichTextBox
editor considered in detail in the article.
Also some advices about RichTextBox
usage are presented. The source code and compiled demo
are attached.
Background
This issue has been repeatedly raised in the Internet community and partially been considered in the CopeProject site:
"Create a RichTextBox with a Toolbar Sample",
"Create your own Format Bar for the WPF RichTextBox",
"A Bindable WPF RichTextBox",
"WPF RichText Editor", and
"WPF RichTextEditor with Toolbar".
Most of the articles are devoted to the question of why the Document
property isn't bindable. And the question of how to create
a good toolbar for the RichTextBox
editor has actually never been seen.
Usually, to solve it developers create a user control that contains a toolbar with
the RichTextBox
editor. But this approach causes a lot of problems, for example, changing the properties of the editor.
In addition to this, all developing projects has an actual problem of timely updating toolbox items.
Another way out of this situation is presented on MSDN at the "Create a RichTextBox with a Toolbar Sample" page.
A simple toolbar that contains buttons bound to standard commands from EditingCommand
s are presented.
They've avoided problems with the update states of such buttons as bold, italic, underline, making
them simple buttons instead of toggle buttons.
Using the code
You can take a look at how simple it is to use the toolbar for formatting the contents of the RichTextBox WPF control proposed in the article. To use it you need to make a reference in your project to the library "RichTextBoxToolBar.dll" and define its namespace:
xmlns:rtb="clr-namespace:RichTextBoxToolBar;assembly=RichTextBoxToolBar"
In order to insert a new formatting toolbar you need to write only one line:
<rtb:RichTextBoxToolBar />
The toolbar will itself bind to the RichTextBox
component that has the keyboard input focus.
If the focus switched to another component than the RichTextBox
, then the items on the toolbox become disabled.
Toolbox items can be always enabled and bound to the last RichTextBox
component that
lost focus. In order to do this you need use the LeftEnabledWhenEditorFocusLost
property:
<rtb:RichTextBoxToolBar LeftEnabledWhenEditorFocusLost="True" />
If you want to bind to a specific instance of a RichTextBox
,
you need to use the TargetEditor
property.
<rtb:RichTextBoxToolBar TargetEditor="{Binding ElementName=_rtb}" />
An example of defining a new RichTextBox
component is presented below:
<RichTextBox
SpellCheck.IsEnabled="True"
AcceptsReturn="True"
AcceptsTab="True">
<RichTextBox.Resources>
<Style TargetType="{x:Type Paragraph}">
<Setter Property="Margin" Value="0" />
</Style>
</RichTextBox.Resources>
</RichTextBox>
The SpellCheck.IsEnabled
attribute enables or disables the spelling checker on the text-editing control.
To enable the spelling checker, set the SpellCheck.IsEnabled
property to true. When this spelling checker is enabled, misspelled words are underlined by using a red wavy line.
The spelling checker is supported only when WPF provides a default dictionary. In .NET Framework 4,
WPF provides dictionaries only for English, French, German, and Spanish.
Getting or setting a value of AcceptsReturn
indicates how the text editing control responds when the user presses the ENTER key.
If the property is set to true
, pressing the ENTER key editor inserts a new line at the current cursor position; otherwise, the editor ignores the ENTER key.
The default value is false
.
Also, the default value is false
for the AcceptTabs
property.
This means that pressing the TAB key moves the focus to the next control that is marked as a tab stop and does not insert a tab character.
If the property is set to
The style tag in the resource is used to set the margin for all Paragraph elements in a
FlowDocument
to 0 to achieve uniform spacing between
paragraphs throughout an entire FlowDocument
(see How to: Adjust Spacing Between Paragraphs).
It should be noted that this approach to solving the problem has several advantages:
-
The independence of the toolbar from the
RichTextBox
editor. - Ease to describe in XAML and to use the toolbar. However, this advantage has a small disadvantage. You can't simply redefine the design of the toolbar.
- All interactions with the
RichTextBox
editor are performed by commands placed inSystem.Windows.Documents.EditingCommands
andRichTextBoxToolBar.EditingCommands
. This feature allows you to execute the commands in other places, such menus, toolbars, buttons.
RichTextBoxToolBar Assembly
The RichTextBoxToolBar assembly contains the following classes:
-
public RichTextBoxToolBar:ToolBar
- Toolbar contained formatting commands. -
LeftEnabledWhenEditorFocusLost:Boolean
- If the dependency property is set totrue
the toolbar is always enabled and bound to the RichTextBox component that had the last keyboard input focus. -
TargetEditor:RichTextBox
- Dependency property contains the object that formatting commands are being executed on. If the property isnull
the target editor is captured automatically by listening to the keyboard got and lost focus events of the root container, such asWindow
,Frame
, and others. -
CurrentEditor:RichTextBox
- Read only dependency property that contains a link to the currentRichTextBox
component in which formatting commands are being executed on. -
IsEnabledToolBarItems:Boolean
- Read only dependency property representing the value indicating whether the user can interact with toolbar items. -
public EdditingCommandsEx
- Provides an extended set of editing related commands. -
ToggleStrikethrough:RoutedUICommand
- Represents theToggleStrikethrough
command, which requests that Strikethrough formatting be toggled on the current selection. -
SelectFontFamily:RoutedUICommand
- Represents theSelectFontFamily
command, which requests that FontFamily formatting be selected on the current selection. The command requires you to pass an additional parameter that specifies the font family being theFontFamily
type. -
SelectFontSize:RoutedUICommand
- Represents theSelectFontSize
command, which requests that FontSize formatting be selected on the current selection. The command requires you to pass an additional parameter that specifies the font size being theDouble
type that contains a positive number or theString
type that can be converted to a positive number. -
SelectBackgroundColor:RoutedUICommand
- Represents theSelectBackgroundColor
command, which requests that Background formatting be selected on the current selection. The command requires you to pass an additional parameter that specifies the background color being theColor
or theSolidColorBrush
type. -
SelectForegroundColor:RoutedUICommand
- Represents theSelectForegroundColor
command, which requests that Foreground formatting be selected on the current selection. The command requires you to pass an additional parameter that specifies the foreground color being theColor
or theSolidColorBrush
type. -
internal KeyboardFocusTrackingElement<ELEMENT> where ELEMENT:IInputElement
- Tracking the got and loss keyboard input focus is implemented in theKeyboardFocusTrackingElement
class. The template parameterELEMENT
is the type of control for which the keyboard focuses tracking. -
FocusedElement:ELEMENT
- Control has the keyboard focus. -
BindingToRoot:Boolean
- Bind to track changing keyboard input focus to the root element (Window
,Frame
, ...) or the current control (CurrentElement
). -
CurrentElement:FrameworkElement
- Relative to the control, searches the root control. If theBindingToRoot
property is set tofalse
andCurrentElement
is ofELEMENT
type then keyboard events bound to the control. -
HiddenElements:IEnumerable<FrameworkElement>
- These controls are skipped when focus changes. -
Bind
- Start monitoring the input focus. -
Unbind
- Stop monitoring the input focus. -
KeyboardFocusChanged:KeyboardFocusChangedEventHandler
- The event occurs when the input focus changes for the control ofELEMENT
type. -
internal RadioButtonsWithoutChecksManager
- Advanced feature for radio buttons allows to switch the active button to inactive state. -
Bind
- Enable the feature. -
Unbind
- Disable the feature. -
internal static RichTextBoxToolBarHelper
- Set of utility methods to work with theRichTextBox
editor.
History
- 28th August, 2012: Initial post.