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 <coe>true, pressing the TAB key editors inserts a tab character at the current cursor position.
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 in System.Windows.Documents.EditingCommands
and RichTextBoxToolBar.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 to true
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 is null
the target editor is captured automatically by listening
to the keyboard got and lost focus events of the root container, such as Window
, Frame
, and others.
-
CurrentEditor:RichTextBox
- Read only dependency property
that contains a link to the current RichTextBox
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 the ToggleStrikethrough
command, which requests that Strikethrough formatting be toggled on the current selection.
-
SelectFontFamily:RoutedUICommand
- Represents the SelectFontFamily
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 the FontFamily
type.
-
SelectFontSize:RoutedUICommand
- Represents the SelectFontSize
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 the Double
type that contains
a positive number or the String
type that can be converted
to a positive number.
-
SelectBackgroundColor:RoutedUICommand
- Represents the SelectBackgroundColor
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 the Color
or the SolidColorBrush
type.
-
SelectForegroundColor:RoutedUICommand
- Represents the SelectForegroundColor
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 the Color
or the SolidColorBrush
type.
-
internal KeyboardFocusTrackingElement<ELEMENT> where ELEMENT:IInputElement
- Tracking the got and loss keyboard input focus is implemented in the KeyboardFocusTrackingElement
class.
The template parameter ELEMENT
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 the BindingToRoot
property
is set to false
and
CurrentElement
is of ELEMENT
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 of ELEMENT
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 the RichTextBox
editor.
History
- 28th August, 2012: Initial post.
Senior lecturer of Nanotechnology department of Physics faculty of Southern Federal University (Russia).
My field of science is the numerical modeling of excitation, propagation and receiving of electromagnetic and acoustic waves in micro- and nanostructures; modeling microwave and optic devices based on ferromagnetic, ferroelectric and semiconducting films and whiskers; study of the periodic structures properties like magnonic and photonic crystals.
I also develop a software for theoretical modeling and experimental studies using modern methods of software engineering, programming languages, numerical methods and mathematical software packages, software platforms, parallel computation and asynchronous programming, database management systems, Web-programming and design, system programming (drivers , communication interfaces, microcontroller programming).
My hobbies are software architecture (UP, UML, TDD, BDD, DI, AOP), programming languages (C#, F#, C++, Java, LabVIEW, Delphi, Perl, PHP, ASP.NET, JavaScript, VBScript, ActionScript, Pascal, Basic, VBA for MS Office, Fortran, Assembler, PowerShell, SQL, VHDL), mathematical methods and mathematical packages (Maple, MatLab, Mathematica), programming for modern electronics (microcontrollers, PLIS, DSP, communication interfaces), Web-design (design, HTML, Flash, Silverlight, Moodle, Joomla, Drupal), technologies (WPF, WCF, WF, ADO.NET, COM, Services, WMI, MFC, jQuery, YUI), System Administration (Windows, Unix), office suites (Microsoft Office, Libre Office, using styles, LaTeX).