Skip to main content

RichTextEditor

Avalonia.Controls.RichTextEditor is a rich text editing solution for Avalonia applications, offering functionalities for interactive text editing, document architecture and file serialization.

info

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.

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

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.

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;

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:

SerializerPackageExtension
RtfSerializerAvalonia.Controls.Documents.Serialization.Rtf.rtf
DocxSerializerAvalonia.Controls.Documents.Serialization.Docx.docx
XamlSerializerAvalonia.Controls.Documents.Serialization.Xaml.xaml
PlainTextSerializerAvalonia.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:

  1. RichTextEditor: Interactive editing control that renders a document and allows users to type, select, format, undo/redo, etc.
  2. FlowDocumentScrollViewer: Read-only viewer that displays a document without editing capabilities.
  3. FlowDocument: Document model that organizes rich text content into blocks.

RichTextEditor properties

These properties are used by the RichTextEditor component.

PropertyTypeDescriptionDefault
AcceptsReturnboolDetermines whether the editor accepts return key input.true
AcceptsTabboolDetermines whether the editor accepts tab key input.true
CaretBrushIBrushColor of the caret (text cursor).None
DocumentFlowDocumentSelects the document to display and edit.None
IsReadOnlyboolDetermines whether the editor is read-only.false
SelectionBrushIBrushColor of text selections.None
SelectionFlyoutEditorSelectionFlyout?Mini toolbar shown above a selection. Set to null to remove it.null
ShowSelectionFlyoutboolShow or hide the selection flyout without replacing it.true
ToolbarEditorToolbarCustomizes toolbar design and layout.Null
ShowBlockAdornersboolDetermines whether block adorner decorations are displayed.true
ShowPageBoundsboolDetermines whether page boundary indicators are displayed.false
ShowToolbarboolDetermines whether the toolbar is visible.true
UndoLimitintMaximum number of operations to retain for undo actions.100

FlowDocument properties

These properties are used by the FlowDocument component.

PropertyTypeDescriptionDefault
BackgroundIBrushColor of the document's background, as an ARGB value.Null
FontFamilyFontFamily Font family for text in the document.Null
FontSizedoubleFont size for text in the document.12
FontStretchFontStretchFont stretch for text in the document, e.g., Normal, Condensed, Expanded.Normal
FontStyleFontStyleFont style for text in the document, e.g., Normal, Italic, Oblique.Null
FontWeightFontWeightFont weight for text in the document, e.g., Normal, Bold.Normal
ForegroundIBrushColor of the document's foreground, as an ARGB value.Null
PageHeightdoubleHeight of the page.double.NaN
PagePaddingThicknessInner spacing between the block's borders and its content.Null
PageWidthdoubleWidth of the page.double.NaN
TextAlignmentTextAlignmentAlignment 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.

ElementDescription
BlockAbstract base class for block elements.
BlockUIContainerWrapper to embed UI elements as blocks.
ListDisplays a bulleted or numbered list.
ListItemIndividual item in a List.
ParagraphBasic block element that contains rich text content.
SectionBlock element that groups other block elements.
TableDisplays a table.
TableCellIndividual cell in a Table.
TableColumnA column of cells in a Table.
TableRowA row of cells in a Table.
TableRowGroupA group of rows in a Table.

Properties

PropertyTypeDescriptionDefault
BackgroundIBrushColor of the block's background, as an ARGB value.Null
BorderBrushIBrushColor of the block's borders, as an ARGB value.Null
BorderThicknessThicknessThickness of the block's borders.Null
CellSpacingdoubleUsed by Table. The spacing between table cells.0
ChildControlUsed by BlockUIContainer. Defines the control to be placed in the block.Null
ColumnSpanintUsed by TableCell. The number of columns the cell spans.1
CornerRadius CornerRadiusThe radius applied to the block's corners.Null
FlowDirectionFlowDirectionDirection of text flow, i.e., LeftToRight or RightToLeft.Null
FontFamilyFontFamily Font family for text in the block.Null
FontFeaturesFontFeatureCollectionA collection of font features applied to text in the block.
FontSizedoubleFont size for text in the block.12
FontStretchFontStretchFont stretch for text in the block, e.g., Normal, Condensed, Expanded.Normal
FontStyleFontStyleFont style for text in the block, e.g., Normal, Italic, Oblique.Null
FontWeightFontWeightFont weight for text in the block, e.g., Normal, Bold.Normal
ForegroundIBrushColor of the block's foreground, as an ARGB value.Null
LetterSpacingdoubleAdditional horizontal spacing between characters. The default of 0 indicates normal spacing.0
LineHeightdoubleHeight of each line of text in the block.double.NaN
MarginThicknessOuter spacing around the block element.Null
MarkerOffsetdoubleUsed by List. Determines the spacing after a list marker.double.NaN
MarkerStyleTextMarkerStyleUsed by List. Selects the style of the list marker, e.g., Disc, Decimal, LowerLatin.Null
PaddingThicknessInner spacing between the block's borders and its content.Null
RowSpanintUsed by TableCell. The number of rows the cell spans.1
StartIndexintUsed by List. Specifies the starting index for numbered lists.1
TabStopPositionsdoublePositions of tab stops for text in the block.double.NaN
TextAlignmentTextAlignmentAlignment of text in the block, i.e., Left, Center, Right, Justify.Null
TextDecorationsTextDecorationsDecorative elements applied to text in the block, e.g., Underline, Overline, Strikethrough.
TextIndentdoubleWidth 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.

ElementDescription
RichBoldIndicates bolded text. Overrides global FontWeight property.
RichHyperlinkMarks an inline hyperlink.
RichInlineAbstract base class for inline elements.
RichInlineUIContainerWrapper to embed UI elements within text flow.
RichItalicIndicates italicized text. Overrides global FontStyle property.
RichLineBreakForces a line break.
RichRunBasic text run. Allows character-level formatting. Text content is defined by the Text property.
RichSpanInline element that groups other inline elements.
RichSubscriptIndicates subscript text. Sets BaselineAlignment property to Subscript.
RichSuperscriptIndicates superscript text. Sets BaselineAlignment property to Superscript.
RichUnderlineIndicates underlined text. Overrides global TextDecorations property.

Properties

PropertyTypeUsed byDescription
ChildControlRichInlineUIContainerDefines the control to be placed in the inline container.
IsVisitedboolRichHyperlinkWhether the hyperlink has been visited.
NavigateURIUriRichHyperlinkThe URI to navigate to when hyperlink is clicked.
TextstringRichRunGets or sets the text content. Reads/writes to the attached TextDocument. If unattached, uses local storage.
TooltipobjectRichHyperlinkTooltip associated with the hyperlink.

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.

LayerNameDescriptionKey components
1Document modelCore data storage of text context and document hierarchy. Uses a rope data structure for efficient storage and operations.TextDocument, TextDocumentNode, RopeTextStore, RopeSnapshot
2Text pointer APIPosition tracking and navigation within documents.TextPointer, TextRange, LogicalDirection
3RenderingVisual representation, coordinate mapping, hit testing, line queries.ITextView, TextViewBase, InteractiveTextView, ITextLine, DocumentNodes
4EditingHandles user input from keyboard, mouse, or other devices.TextSelection, TextEditorTyping, TextEditorKeyboard, TextEditorMouse, CaretElement
5HighlightingVisual effects for highlighting, used in selections, annotations, find/replace, etc.IHighlightLayer, HighlightLayerBase, SelectionHighlightLayer
6Undo/RedoStores operation history to allow reversals.IUndoManager, UndoManager
7SerializationImport and export documents in multiple formats (RTF, DOCX, XAML, plain text).IDocumentSerializer, DocumentSnapshot, FlowDocumentBuilder
8User-facing controlIntegration of all layers into a templated Avalonia control.RichTextEditor, FlowDocument, Block elements, Inline elements

See also