Controls
RichTextBox
RichTextBox is the interactive host for structured rich documents. It owns focus, caret and selection state, editing commands, scrolling, rendering, hyperlink activation, and the control-template contract. The document tree it hosts is covered separately on the RichTextDocument page.
Mental model
The control
RichTextBox behaves like an editor surface: it receives input, manages selection and caret visibility, executes editing commands, and renders the live document viewport.
The model
The hosted document is still a structured tree of blocks and inlines. When you need to reason about paragraphs, runs, lists, tables, or hosted UI, jump to RichTextDocument.
Choose the layer deliberately. Reach for RichTextBox when your problem is about editing behavior or UI integration. Reach for RichTextDocument when your problem is about document structure or serialization.
Quick start
Minimal editor surface
<RichTextBox Width="520"
Height="260"
Padding="8"
BorderThickness="1"
TextWrapping="Wrap" />
Assign a document
var document = new FlowDocument();
var paragraph = new Paragraph();
paragraph.Inlines.Add(new Run("Edit me"));
document.Blocks.Add(paragraph);
editor.Document = document;
Read-only rich viewer
<RichTextBox Width="560"
Height="280"
IsReadOnly="True"
TextWrapping="Wrap" />
What the control owns
- Keyboard and pointer editing gestures, including word motion, selection extension, paragraph breaks, list commands, and hyperlink activation.
- Caret and selection state through both integer offsets and document-aware pointer or range APIs.
- Undo or redo orchestration through the document undo manager.
- Viewport scrolling, caret visibility, auto-scroll during drag selection, and wheel handling.
- Rendering of the document surface, selection geometry, caret, table lines, and hosted document children.
Inspect selection state
Console.WriteLine(editor.CaretIndex);
Console.WriteLine(editor.SelectionStart);
Console.WriteLine(editor.SelectionLength);
Hit test into the document
TextPointer? pointer = editor.GetPositionFromPoint(mousePosition, snapToText: true);
if (pointer.HasValue)
{
var offset = DocumentPointers.GetDocumentOffset(pointer.Value);
Console.WriteLine($"Hit offset: {offset}");
}
Working with the document
RichTextBox always hosts a valid document. Setting Document to null is coerced back to a default document, and whole-document operations are intentionally separate from selection-scoped operations.
Whole-document APIs
Use Document, Load, and Save when you want to replace or serialize the complete document.
Selection APIs
Use Select, LoadSelection, and SaveSelection when the operation should affect only the current range.
Whole-document load
using var stream = new MemoryStream(Encoding.UTF8.GetBytes(payload));
editor.Load(stream, "Xaml");
Selection-scoped load
using var stream = new MemoryStream(Encoding.UTF8.GetBytes("Inserted text"));
editor.LoadSelection(stream, "Text");
Document structure is preserved by default. The editor will preserve rich fragments during selection edits, clipboard operations, and many command-driven transformations. The full model details live on the RichTextDocument guide.
Commands and shortcuts
Toolbar buttons, keyboard shortcuts, and explicit command execution all go through the same routed command surface.
Core editing
Backspace, delete, copy, cut, paste, undo, redo, select-all, paragraph breaks, line breaks, and word navigation.
Rich editing
Formatting toggles, list indent or outdent, table insertion, cell split or merge, document navigation, and hyperlink activation.
Formatting commands
CommandManager.Execute(EditingCommands.ToggleBold, null, editor);
CommandManager.Execute(EditingCommands.ToggleItalic, null, editor);
CommandManager.Execute(EditingCommands.ToggleUnderline, null, editor);
Structure commands
CommandManager.Execute(EditingCommands.ToggleBullets, null, editor);
CommandManager.Execute(EditingCommands.InsertTable, null, editor);
CommandManager.Execute(EditingCommands.SplitCell, null, editor);
Serialization and clipboard
The control supports both rich and plain formats. Rich formats preserve more structure; text formats flatten the document.
- Rich formats include
Flow XML,Xaml,XamlPackage, andRich Text Format. - Plain formats include
TextandUnicodeText. SaveSelectionandLoadSelectionlet you round-trip only the active fragment.
Save the whole document
using var stream = new MemoryStream();
editor.Save(stream, FlowDocumentSerializer.ClipboardFormat);
Save only the current selection
using var stream = new MemoryStream();
editor.SaveSelection(stream, "Xaml");
Layout, templating, and rendering
The control template provides outer chrome only. RichTextBox still owns the rich document viewport and rendering behavior.
Template contract
The default template must expose PART_ContentHost so the control aligns with the rest of the text-input family.
Control-owned surface
Selection, caret, rendered runs, table borders, and hosted document UI are still drawn and managed by the control itself.
Template example
<Style TargetType="{x:Type RichTextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RichTextBox}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ScrollViewer x:Name="PART_ContentHost"
Margin="{TemplateBinding Padding}"
Focusable="False" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Events and integration points
DocumentChangedfires when the document is replaced or mutates internally.TextChangedfires for text-affecting edits.SelectionChangedtracks caret and selection transitions.HyperlinkNavigatebubbles the activated target URI.
Subscribe to the main events
editor.DocumentChanged += (_, _) => Console.WriteLine("Document changed");
editor.TextChanged += (_, _) => Console.WriteLine("Text changed");
editor.SelectionChanged += (_, _) => Console.WriteLine("Selection changed");
editor.HyperlinkNavigate += (_, args) => Console.WriteLine(args.NavigateUri);
When to use it
Use TextBox for plain text. Use RichTextBox when the UI problem includes rich selection, structured clipboard content, hyperlinks, lists, tables, or hosted UI inside the document.
Go deeper on the model. For blocks, inlines, tables, hosted UI containers, and example-rich document construction patterns, continue to RichTextDocument.