This document describes how the TextView class renders the text, and how you can extend the text rendering process to add new features to the text editor. The T:ICSharpCode.AvalonEdit.Rendering.TextView class is the heart of AvalonEdit. It takes care of getting the document onto the screen. To do this in an extensible way, the TextView uses its own kind of model: the T:ICSharpCode.AvalonEdit.Rendering.VisualLine. Visual lines are created only for the visible part of the document. The rendering process looks like this: The "element generators", "line transformers" and "background renderers" are the extension points; it is possible to add custom implementations of them to the TextView to implement additional features in the editor.
Lifetime of VisualLines VisualLines are only created for the visible part of the document. Lots of actions can trigger their creation, but most commonly the creation will be caused by the MeasureOverride method of TextView. When the TextView is measured, it uses the height tree to determine the first document line in the visible region. Then, it constructs and measures a VisualLine for that first line, and repeats that with the following lines until the visible region is filled. The TextView caches VisualLines - when the user scrolls down, only the VisualLines coming into view are created, the rest is reused. The VisualLine cache can be manually invalidated using the Redraw method family; moreover, lots of actions cause automatic invalidation: any change in the document will invalidate the affected VisualLineschanging the width of the TextView invalidates all VisualLines if word-wrap is enabledchanging any text editor settings (word-wrap, font size, etc.) will invalidate all VisualLinesVisualLines leaving the visible area after scrolling will be disposed In general, manual invalidation is required only if you have written a text editor extension (BackgroundRenderer, VisualLineElementGenerator or VisualLineTransformer) that also consumes external data - in that case, you'll have to notify the text editor that VisualLines need to be recreated when your external data changes. If external data used by your text editor extension changes, call M:ICSharpCode.AvalonEdit.Rendering.TextView.Redraw to invalidate the VisualLine. Invalidating VisualLines does not cause immediate recreation of the lines! Rather, the VisualLines are recreated when the text view is next re-measured. While measurement in WPF normally happens with DispatcherPriority.Render, the TextView also supports redrawing with a lower priority than that. For example, normal text insertion causes a redraw at background priority, so that in case the user types faster than the text view can redraw, there will be only one redraw for multiple input actions. The TextView will never return invalid lines to you, but you may run into the case that the valid visual lines are not available. What happens in this case depends on the method you are calling - the new visual line might get created automatically, null could be returned, or you may get a T:ICSharpCode.AvalonEdit.Rendering.VisualLinesInvalidException. You can call M:ICSharpCode.AvalonEdit.Rendering.TextView.EnsureVisualLines to make the text view create all VisualLines in the visible region.
Building visual line elements As a first step, the VisualLineElementGenerators are used to produce elements. The room in between the elements returned from the generators is filled with text elements. Then, the VisualLine assigns the VisualColumn and RelativeTextOffset properties of the line elements. For example, a line contains the text "Hello, World". The user has enabled "ShowSpaces", so the text editor should show a little dot instead of the space. In this case, the SingleCharacterElementGenerator, which is responsible for ShowSpaces, will produce a "SpaceTextElement" for the space character. Because no other generators are interested in the line, the remaining strings "Hello," and "World" will be represented by VisualLineText elements.
Transforming visual line elements After that, the IVisualLineTransformers are used to modify the produced line elements. Transformers must not add elements, but they may split existing elements, e.g. to colorize only parts of an element. When splitting elements (or somehow modifying the elements collection), care must be taken that the VisualColumn,VisualLine,RelativeTextOffset and DocumentLength properties stay correct. The ColorizingTransformer base class provides helper methods for splitting, so the derived class can simply say "color this section in that color". The DocumentColorizingTransformer extends the ColorizingTransformer and additionally allows highlighting on per DocumentLine, coloring text segments (instead of directly working with visual line elements).
Constructing TextLines After building the visual line elements, the TextLines for the visual line are constructed. A visual line may result in multiple text lines when word wrapping is active or when special visual line elements force a line break. Building text lines: The text line construction is done by a WPF TextFormatter. The VisualLineTextSource will take the visual line elements and build WPF TextRuns from it, while the WPF TextFormatter takes care of word wrapping etc. VisualLineElements are requested to produce TextRuns for their full or a partial length. The TextView will take care to measure any inline UI elements in the visual lines.
Rest of the Rendering After the visible region is filled, the TextView updates the heights stored in the document lines to the measured heights. This way, scrolling takes account for word-wrapping. The constructed text lines are stored for the arrange and render steps. Now, finally, the measure step is complete. The WPF arrange step doesn't have much work to do: It just arranges inline UI elements at their position inside the text. The actual rendering does not happen directly in the TextView, but in its various layers. These are the predefined layers: Background layer: renders the background colors associated with the visual elementsSelection layer: renders the background of the selectionText layer: renders the TextLines that were constructed during the Measure step. The text layer also serves as container for any inline UI elements. Caret layer: renders a blinking caret It's also possible to insert new layers into the TextView using the M:ICSharpCode.AvalonEdit.Rendering.TextView.InsertLayer(System.Windows.UIElement,ICSharpCode.AvalonEdit.Rendering.KnownLayer,ICSharpCode.AvalonEdit.Rendering.LayerInsertionPosition) method. This allows adding custom interactive components to the editor while being in full control of the Z-Order.
T:ICSharpCode.AvalonEdit.Rendering.TextView