Click here to Skip to main content
Click here to Skip to main content

WPF RichTextBoxToolBar Control

, 27 Aug 2012
Rate this:
Please Sign up or sign in to vote.
Developing an easy to use toolbar for formatting the contents of a RichTextBox WPF control.

Demonstration of RichTextBoxToolBar Controls

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 EditingCommands 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 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

Classdiagram of RichTextBoxToolBar Control

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Pavel Evgenjevich Timoshenko
Instructor / Trainer Southern Federal University
Russian Federation Russian Federation
Engineer and assistant of the nanotechnology department of physics faculty of Southern Federal University (Russia).
 
My field of science is methods of computing microwave electrodynamics and spin electronics.
 
My interests: software architecture (development process optimization, UP, modeling, 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), 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, processing of documents, styles, LaTeX).

Comments and Discussions

 
QuestionNice work! But very bad performance PinmemberLumoWIT11-Jun-14 1:08 
GeneralMy vote of 3 PinmemberClifford Nelson3-Sep-13 13:50 
BugWhy are you using 4.5 PinmemberClifford Nelson3-Sep-13 13:43 
GeneralMy vote of 5 PinmvpKanasz Robert19-Sep-12 4:54 
GeneralNice work! Pinmemberkorsarz3313-Sep-12 6:19 
Question.NET 4.5 PinmemberRichard Deeming5-Sep-12 7:46 
AnswerRe: .NET 4.5 PinmemberPavel Evgenjevich Timoshenko5-Sep-12 10:16 
AnswerRe: .NET 4.5 Pinmembervoodark21-Feb-14 5:28 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140721.1 | Last Updated 27 Aug 2012
Article Copyright 2012 by Pavel Evgenjevich Timoshenko
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid