RichTextEditor
Avalonia.Controls.RichTextEditor is a rich text editing solution for Avalonia applications, offering functionalities for interactive text editing, document architecture and file serialization.
This control is available as part of Avalonia Pro or higher.
When to use
Use RichTextEditor to create an area where users can edit text content and perform common text operations, such as formatting, aligning, highlighting, or undo/redo.
Basic usage
Use this setup to get started with a basic implementation of the rich text editor.
- XAML
- Code-behind
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="My Rich Text Editor"
Width="800" Height="600">
<RichTextEditor x:Name="Editor">
<RichTextEditor.Document>
<FlowDocument>
<Paragraph>
<RichRun Text="Welcome to " />
<RichBold>
<RichRun Text="RichTextEditor" />
</RichBold>
<RichRun Text="!" />
</Paragraph>
</FlowDocument>
</RichTextEditor.Document>
</RichTextEditor>
</Window>
using Avalonia.Controls;
using Avalonia.Controls.Documents;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var editor = this.FindControl<RichTextEditor>("Editor");
// Undo/redo is ready to use — the editor creates an UndoManager
// automatically when a Document is attached.
// To change the limit:
// editor.UndoLimit = 50;
}
}
Programmatic document construction
If preferred, you can create and edit documents from the code-behind instead of XAML. Do this by directly calling the relevant components, block elements, or inline elements from Avalonia.Controls.Documents.
- Create document
- Insert text
- Format selected text
var document = new FlowDocument();
var paragraph = new Paragraph();
paragraph.Inlines.Add(new RichRun("Hello "));
paragraph.Inlines.Add(new RichBold(new RichRun("World")));
paragraph.Inlines.Add(new RichRun("!"));
document.Blocks.Add(paragraph);
editor.Document = document;
var doc = editor.Document?.TextDocument;
if (doc != null)
{
// Insert at start
doc.ContentStart.InsertText("Header: ");
// Insert at end
doc.ContentEnd.InsertText("\n\nFooter");
}
var doc = editor.Document?.TextDocument;
if (doc != null)
{
var range = new TextRange(doc.ContentStart, doc.ContentStart.GetPositionAtOffset(10));
range.ApplyPropertyValue(RichTextElement.ForegroundProperty, Brushes.Red);
range.ApplyPropertyValue(RichTextElement.FontSizeProperty, 20.0);
}
Loading and saving files
Load and Save accept an IDocumentSerializer instance. Each format lives in its own package.
using Avalonia.Controls.Documents.Serialization.Rtf;
// Load RTF (async, preferred)
await using (var stream = File.OpenRead("document.rtf"))
{
await editor.LoadAsync(stream, new RtfSerializer());
}
// Save RTF (async, preferred)
await using (var stream = File.Create("output.rtf"))
{
await editor.SaveAsync(stream, new RtfSerializer());
}
Synchronous overloads are also available:
editor.Load(stream, new RtfSerializer());
editor.Save(stream, new RtfSerializer());
Available serializers:
| Serializer | Package | Extension |
|---|---|---|
RtfSerializer | Avalonia.Controls.Documents.Serialization.Rtf | .rtf |
DocxSerializer | Avalonia.Controls.Documents.Serialization.Docx | .docx |
XamlSerializer | Avalonia.Controls.Documents.Serialization.Xaml | .xaml |
PlainTextSerializer | Avalonia.Controls.Documents (core) | .txt |
Loading a document without an editor
FlowDocument.LoadAsync creates a document directly from a stream, useful for preview or conversion scenarios:
await using var stream = File.OpenRead("document.rtf");
var document = await FlowDocument.LoadAsync(stream, new RtfSerializer());
Adding a word counter
You can create an event that returns a word count. In this example, we add a continuous word counter that updates when the text changes.
editor.ContentChanged += (sender, args) =>
{
Console.WriteLine("Document changed");
UpdateWordCount();
};
void UpdateWordCount()
{
string? text = editor.Document?.ContentRange?.Text;
if (text != null)
{
int wordCount = text.Split(new[] { ' ', '\n', '\r' },
StringSplitOptions.RemoveEmptyEntries).Length;
Console.WriteLine($"Word count: {wordCount}");
}
}
Customizing selection highlight color
The highlight color of text selections can be customized by specifying an ARGB value for SelectionBrush.
<RichTextEditor SelectionBrush="#ffff529e">
Components
The Avalonia rich text editor consists of three components:
RichTextEditor: Interactive editing control that renders a document and allows users to type, select, format, undo/redo, etc.FlowDocumentScrollViewer: Read-only viewer that displays a document without editing capabilities.FlowDocument: Document model that organizes rich text content into blocks.
RichTextEditor properties
These properties are used by the RichTextEditor component.
| Property | Type | Description | Default |
|---|---|---|---|
AcceptsReturn | bool | Determines whether the editor accepts return key input. | true |
AcceptsTab | bool | Determines whether the editor accepts tab key input. | true |
CaretBrush | IBrush | Color of the caret (text cursor). | None |
Document | FlowDocument | Selects the document to display and edit. | None |
IsReadOnly | bool | Determines whether the editor is read-only. | false |
SelectionBrush | IBrush | Color of text selections. | None |
SelectionFlyout | EditorSelectionFlyout? | Mini toolbar shown above a selection. Set to null to remove it. | null |
ShowSelectionFlyout | bool | Show or hide the selection flyout without replacing it. | true |
Toolbar | EditorToolbar | Customizes toolbar design and layout. | Null |
ShowBlockAdorners | bool | Determines whether block adorner decorations are displayed. | true |
ShowPageBounds | bool | Determines whether page boundary indicators are displayed. | false |
ShowToolbar | bool | Determines whether the toolbar is visible. | true |
UndoLimit | int | Maximum number of operations to retain for undo actions. | 100 |
FlowDocument properties
These properties are used by the FlowDocument component.
| Property | Type | Description | Default |
|---|---|---|---|
Background | IBrush | Color of the document's background, as an ARGB value. | Null |
FontFamily | FontFamily | Font family for text in the document. | Null |
FontSize | double | Font size for text in the document. | 12 |
FontStretch | FontStretch | Font stretch for text in the document, e.g., Normal, Condensed, Expanded. | Normal |
FontStyle | FontStyle | Font style for text in the document, e.g., Normal, Italic, Oblique. | Null |
FontWeight | FontWeight | Font weight for text in the document, e.g., Normal, Bold. | Normal |
Foreground | IBrush | Color of the document's foreground, as an ARGB value. | Null |
PageHeight | double | Height of the page. | double.NaN |
PagePadding | Thickness | Inner spacing between the block's borders and its content. | Null |
PageWidth | double | Width of the page. | double.NaN |
TextAlignment | TextAlignment | Alignment of text in the document, i.e., Left, Center, Right, Justify. | Null |
Block elements
Block elements are used by FlowDocument to build the document model and organize content.
| Element | Description |
|---|---|
Block | Abstract base class for block elements. |
BlockUIContainer | Wrapper to embed UI elements as blocks. |
List | Displays a bulleted or numbered list. |
ListItem | Individual item in a List. |
Paragraph | Basic block element that contains rich text content. |
Section | Block element that groups other block elements. |
Table | Displays a table. |
TableCell | Individual cell in a Table. |
TableColumn | A column of cells in a Table. |
TableRow | A row of cells in a Table. |
TableRowGroup | A group of rows in a Table. |
Properties
| Property | Type | Description | Default |
|---|---|---|---|
Background | IBrush | Color of the block's background, as an ARGB value. | Null |
BorderBrush | IBrush | Color of the block's borders, as an ARGB value. | Null |
BorderThickness | Thickness | Thickness of the block's borders. | Null |
CellSpacing | double | Used by Table. The spacing between table cells. | 0 |
Child | Control | Used by BlockUIContainer. Defines the control to be placed in the block. | Null |
ColumnSpan | int | Used by TableCell. The number of columns the cell spans. | 1 |
CornerRadius | CornerRadius | The radius applied to the block's corners. | Null |
FlowDirection | FlowDirection | Direction of text flow, i.e., LeftToRight or RightToLeft. | Null |
FontFamily | FontFamily | Font family for text in the block. | Null |
FontFeatures | FontFeatureCollection | A collection of font features applied to text in the block. | |
FontSize | double | Font size for text in the block. | 12 |
FontStretch | FontStretch | Font stretch for text in the block, e.g., Normal, Condensed, Expanded. | Normal |
FontStyle | FontStyle | Font style for text in the block, e.g., Normal, Italic, Oblique. | Null |
FontWeight | FontWeight | Font weight for text in the block, e.g., Normal, Bold. | Normal |
Foreground | IBrush | Color of the block's foreground, as an ARGB value. | Null |
LetterSpacing | double | Additional horizontal spacing between characters. The default of 0 indicates normal spacing. | 0 |
LineHeight | double | Height of each line of text in the block. | double.NaN |
Margin | Thickness | Outer spacing around the block element. | Null |
MarkerOffset | double | Used by List. Determines the spacing after a list marker. | double.NaN |
MarkerStyle | TextMarkerStyle | Used by List. Selects the style of the list marker, e.g., Disc, Decimal, LowerLatin. | Null |
Padding | Thickness | Inner spacing between the block's borders and its content. | Null |
RowSpan | int | Used by TableCell. The number of rows the cell spans. | 1 |
StartIndex | int | Used by List. Specifies the starting index for numbered lists. | 1 |
TabStopPositions | double | Positions of tab stops for text in the block. | double.NaN |
TextAlignment | TextAlignment | Alignment of text in the block, i.e., Left, Center, Right, Justify. | Null |
TextDecorations | TextDecorations | Decorative elements applied to text in the block, e.g., Underline, Overline, Strikethrough. | |
TextIndent | double | Width of indentation before the first line of text. Negative value can be set to create a handing indent. | double.NaN |
Inline elements
Inline elements are used to specify content styles within a block.
| Element | Description |
|---|---|
RichBold | Indicates bolded text. Overrides global FontWeight property. |
RichHyperlink | Marks an inline hyperlink. |
RichInline | Abstract base class for inline elements. |
RichInlineUIContainer | Wrapper to embed UI elements within text flow. |
RichItalic | Indicates italicized text. Overrides global FontStyle property. |
RichLineBreak | Forces a line break. |
RichRun | Basic text run. Allows character-level formatting. Text content is defined by the Text property. |
RichSpan | Inline element that groups other inline elements. |
RichSubscript | Indicates subscript text. Sets BaselineAlignment property to Subscript. |
RichSuperscript | Indicates superscript text. Sets BaselineAlignment property to Superscript. |
RichUnderline | Indicates underlined text. Overrides global TextDecorations property. |
Properties
| Property | Type | Used by | Description |
|---|---|---|---|
Child | Control | RichInlineUIContainer | Defines the control to be placed in the inline container. |
IsVisited | bool | RichHyperlink | Whether the hyperlink has been visited. |
NavigateURI | Uri | RichHyperlink | The URI to navigate to when hyperlink is clicked. |
Text | string | RichRun | Gets or sets the text content. Reads/writes to the attached TextDocument. If unattached, uses local storage. |
Tooltip | object | RichHyperlink | Tooltip associated with the hyperlink. |
RichHyperlink pseudoclasses
RichHyperlink sets the following pseudoclasses when the hyperlink text undergoes a state change.
:pointerover: When the pointer is detected stopping over the hyperlink.:pressed: When the hyperlink is clicked.:visited: After the hyperlink has been clicked at least once.
Architecture
The Avalonia rich text editor separates functions into an eight-layer architecture.
| Layer | Name | Description | Key components |
|---|---|---|---|
| 1 | Document model | Core data storage of text context and document hierarchy. Uses a rope data structure for efficient storage and operations. | TextDocument, TextDocumentNode, RopeTextStore, RopeSnapshot |
| 2 | Text pointer API | Position tracking and navigation within documents. | TextPointer, TextRange, LogicalDirection |
| 3 | Rendering | Visual representation, coordinate mapping, hit testing, line queries. | ITextView, TextViewBase, InteractiveTextView, ITextLine, DocumentNodes |
| 4 | Editing | Handles user input from keyboard, mouse, or other devices. | TextSelection, TextEditorTyping, TextEditorKeyboard, TextEditorMouse, CaretElement |
| 5 | Highlighting | Visual effects for highlighting, used in selections, annotations, find/replace, etc. | IHighlightLayer, HighlightLayerBase, SelectionHighlightLayer |
| 6 | Undo/Redo | Stores operation history to allow reversals. | IUndoManager, UndoManager |
| 7 | Serialization | Import and export documents in multiple formats (RTF, DOCX, XAML, plain text). | IDocumentSerializer, DocumentSnapshot, FlowDocumentBuilder |
| 8 | User-facing control | Integration of all layers into a templated Avalonia control. | RichTextEditor, FlowDocument, Block elements, Inline elements |
See also
- Document Viewer — read-only
FlowDocumentScrollViewersetup - Toolbar and Selection Flyout — customizing the toolbar, mini-bar, and context menu
- Extension Patterns — custom nodes, highlight layers, serializers, components
- Performance Tuning
- Troubleshooting