Skip to main content

RichTextEditor control

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.

Getting started​

  1. Install the Avalonia.Controls.RichTextEditor and Avalonia.Controls.Documents NuGet packages by running dotnet add package. Optionally, install serializers for specific file formats you need.
# Editor control
dotnet add package Avalonia.Controls.RichTextEditor

# Core document model, includes plain text serializer
dotnet add package Avalonia.Controls.Documents

# Serializers (add only what you need)
dotnet add package Avalonia.Controls.Documents.Serialization.Rtf # RTF support
dotnet add package Avalonia.Controls.Documents.Serialization.Docx # DOCX (Open XML) support
dotnet add package Avalonia.Controls.Documents.Serialization.Xaml # XAML serialization
dotnet add package Avalonia.Controls.Documents.Serialization.Html # HTML import (read only)
dotnet add package Avalonia.Controls.Documents.Serialization.Pdf # PDF export (write only)
dotnet add package Avalonia.Controls.Markdown # Markdown viewer and serializer
  1. Include your Avalonia license key in the executable project file (.csproj). Your license key is available from the Avalonia portal.
<ItemGroup>
<AvaloniaUILicenseKey Include="YOUR_LICENSE_KEY" />
</ItemGroup>
tip

For multi-project solutions, you can store your licence key in an environment variable or a shared props file to avoid duplication.

  1. Reference the RichTextEditor default theme via a StyleInclude in your App.axaml file. This adds the resources needed to render the control.
<Application.Styles>
<StyleInclude Source="avares://Avalonia.Controls.RichTextEditor/Themes/Default.axaml" />
<!-- other styles -->
</Application.Styles>

For more information on installing Avalonia Pro controls, see Installing Avalonia Pro.

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, keeping the parse off the UI thread
await using (var stream = File.OpenRead("document.rtf"))
{
await editor.LoadAsync(stream, new RtfSerializer());
}

// Save RTF, keeping the write off the UI thread
await using (var stream = File.Create("output.rtf"))
{
await editor.SaveAsync(stream, new RtfSerializer());
}

Synchronous overloads are also available, and run the whole cost on the calling thread:

editor.Load(stream, new RtfSerializer());
editor.Save(stream, new RtfSerializer());
info

IDocumentSerializer is synchronous only. No format performs asynchronous I/O, even with LoadAsync and SaveAsync, which are designed to offload work from the thread by wrapping the call in Task.Run. LoadAsync parses on the thread pool and then builds the element tree on the UI thread, because a FlowDocument and its elements belong to the dispatcher of the thread that constructed them.

Available serializers:

SerializerPackageExtensionDirection
RtfSerializerAvalonia.Controls.Documents.Serialization.Rtf.rtfRead and write
DocxSerializerAvalonia.Controls.Documents.Serialization.Docx.docxRead and write
XamlSerializerAvalonia.Controls.Documents.Serialization.Xaml.xamlRead and write
MarkdownSerializerAvalonia.Controls.Markdown.mdRead and write
HtmlSerializerAvalonia.Controls.Documents.Serialization.Html.htmlRead only (CanWrite is false)
PdfSerializerAvalonia.Controls.Documents.Serialization.Pdf.pdfWrite only (CanRead is false)
PlainTextSerializerIncluded in Avalonia.Controls.Documents (core).txtRead and write

Each serializer reports its direction through CanRead and CanWrite, so a format picker can filter the list.

PdfSerializer is the supported route to paper.

Loading a document without an editor​

FlowDocument.Load and FlowDocument.LoadAsync create a document directly from a stream, useful for preview or conversion scenarios. Both take an optional CancellationToken:

await using var stream = File.OpenRead("document.rtf");
var document = await FlowDocument.LoadAsync(stream, new RtfSerializer(), cancellationToken);

To load with no UI thread involved at all, you can read a DocumentSnapshot with the serializer and materialize it with TextDocument.FromSnapshot, which carries the whole document.

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?.GetText();
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 four 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 as one continuous column, without editing capabilities.
  3. FlowDocumentPageViewer: Read-only viewer that displays a document as discrete page sheets, the way a word processor's print layout does. It derives from FlowDocumentScrollViewer.
  4. FlowDocument: Document model that organizes rich text content into blocks.

A document also owns two kinds of nested document, each a FlowDocument in its own right: page bands (running headers and footers, in FlowDocument.PageBands) and footnotes (in FlowDocument.Footnotes). One editor retargets to whichever of them the caret is in; there is no nested RichTextEditor.

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
CaretBrushIBrush?Color of the caret (text cursor).None
DocumentFlowDocumentSelects the document to display and edit.A new empty FlowDocument
IsReadOnlyboolDetermines whether the editor is read-only.false
PageBandDistancedoubleDistance from the sheet edge to a running header or footer. Writes through to the document, which owns the value.12.5 mm
PageGapdoubleGap between page sheets in page layout.24
PageMarginsThickness?Page margins used in page layout. Falls back to the document's PagePadding.null
PageSizeSize?Page size used in page layout. Falls back to the document's page dimensions, then A4.null
SelectionBrushIBrush?Color of text selections.None
SelectionFlyoutEditorSelectionFlyout?Mini toolbar shown above a selection. Set to null to remove it.null (the default theme supplies one)
ShowBlockAdornersboolDetermines whether block adorner decorations are displayed.true
ShowPageBandsInContinuousLayoutboolIn continuous layout, shows the running header above the first block and the running footer below the last. No effect in page layout.false
ShowPageBoundsboolDetermines whether page boundary indicators are displayed.false
ShowSelectionFlyoutboolShow or hide the selection flyout without replacing it.true
ShowToolbarboolDetermines whether the toolbar is visible.true
ToolbarEditorToolbar?Customizes toolbar design and layout.null (the default theme supplies one)
UndoLimitintMaximum number of operations to retain for undo actions.100
ViewModeDocumentViewModeContinuous for one flowing column, PageLayout for discrete page sheets.Continuous

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
FootnoteNumberFormatFootnoteNumberFormatNumbering used for footnote anchors, e.g., Decimal, LowerRoman, Symbols.Decimal
ForegroundIBrushColor of the document's foreground, as an ARGB value.Null
PageBandDistancedoubleDistance from the sheet edge to a running header or footer. NaN means the document declares none and the default applies.double.NaN
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

FlowDocument also owns two collections of nested documents: PageBands (running headers and footers) and footnotes. Both survive a snapshot round trip and join their undo to the owning document's, so they are present whether or not any element is realized.

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. Carries its own PageWidth, PageHeight and PagePadding, so page setup can vary per section.
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
BreakPageBeforeboolStarts the block on a new page in paged layout, print and PDF export. Ctrl+Enter sets it.false
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
HeightdoubleUsed by TableRow. Minimum row height. Zero sizes the row to its content.0
InsideBorderBrushIBrush?Used by Table. Color of the interior gridlines between cells.Null
InsideBorderThicknessdoubleUsed by Table. Thickness of the interior gridlines between cells.0
KeepTogetherboolKeeps the whole block on one page rather than splitting it across a page break.false
KeepWithNextboolKeeps the block on the same page as the block that follows it.false
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
MarkerAlignmentTextAlignmentUsed by List. Aligns the marker within its column, Left or Right.Left
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
TabStopPositionsIReadOnlyList<double>?Positions of tab stops for text in the block.Null
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
VerticalAlignmentVerticalAlignmentUsed by TableCell. Aligns the cell's content within the row height, Top, Center or Bottom.Top
WidowControlboolUsed by Paragraph. Keeps at least two lines of the paragraph on each side of a page break.true

Inline elements​

Inline elements are used to specify content styles within a block.

ElementDescription
RichBoldIndicates bolded text. Overrides global FontWeight property.
RichFootnoteCitationA further citation of a note whose anchor is elsewhere. Paired with a Footnote by NoteId.
RichFootnoteReferenceAtomic anchor for a footnote, paired with a Footnote in FlowDocument.Footnotes by NoteId.
RichHyperlinkMarks an inline hyperlink.
RichImageInline image. Content comes from a RichImageSource. Occupies a single object replacement character.
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.
RichPageNumberFieldPage number field, CurrentPage or PageCount. Stores no number: the value comes from pagination, so one header band renders a different one per page.
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
AltTextstring?RichImageAlternative text for the image.
ChildControlRichInlineUIContainerDefines the control to be placed in the inline container.
HeightdoubleRichImageDisplay height in device-independent pixels. Unset uses the image's intrinsic height.
IsVisitedboolRichHyperlinkWhether the hyperlink has been visited.
KindPageNumberFieldKindRichPageNumberFieldCurrentPage or PageCount.
NavigateUriUri?RichHyperlinkThe URI to navigate to when hyperlink is clicked.
NoteIdintRichFootnoteReference, RichFootnoteCitationPairs the anchor with its Footnote.
SourceRichImageSource?RichImageThe image content. EmbeddedImageSource, DeferredImageSource or PixelImageSource.
TextstringRichRunGets or sets the text content. Reads/writes to the attached TextDocument. If unattached, uses local storage.
ToolTipobject?RichHyperlinkTooltip associated with the hyperlink.
UnderlineStyleUnderlineStyle?All inlinesThe underline variant, e.g., Single, Double, Dotted, Wave. Inherited.
WidthdoubleRichImageDisplay width in device-independent pixels. Unset uses the image's intrinsic width.

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, FlowDocument
2Text pointer APIPosition tracking and navigation within documents. TextRange owns positional mutation.TextPointer, TextRange, LogicalDirection
3RenderingVisual representation, coordinate mapping, hit testing, line queries. Views can be extended with a component or a highlight layer, but not by subclassing.ITextView, TextViewBase, InteractiveTextView, PagedTextView, ITextLine, DocumentNode
4EditingHandles user input from keyboard, mouse, or other devices.TextSelection, TextViewKeyboard, TextViewMouse, TextEditorKeyboard, CaretElement
5HighlightingVisual effects for highlighting, used in selections, annotations, find/replace, etc.IHighlightLayer, HighlightLayerBase, HighlightLayerCollection, SelectionHighlightLayer
6Undo/RedoStores operation history to allow reversals. UndoManager is the single sealed implementation; there is no undo interface to substitute.UndoManager, IUndoUnit, IUndoScope, SelectionSnapshot
7SerializationImport and export documents in multiple formats (RTF, DOCX, XAML, HTML, Markdown, PDF, plain text). Serializers are synchronous and UI-free.IDocumentSerializer, DocumentSnapshot, DocumentSnapshotBuilder
8User-facing controlIntegration of all layers into a templated Avalonia control.RichTextEditor, FlowDocumentScrollViewer, FlowDocumentPageViewer, FlowDocument, block and inline elements

See also​