Coordinate Systems

The text editor makes use of several different coordinate systems. Here's an explanation of them.


In AvalonEdit, an index into the document is called an offset.

Offsets usually represent the position between two characters. The first offset at the start of the document is 0; the offset after the first char in the document is 1. The last valid offset is document.TextLength, representing the end of the document. This is exactly the same as the index parameter used by methods in the .NET String or StringBuilder classes.


The ICSharpCode.AvalonEdit.Document..::..TextLocation struct represents a Line/Column pair. Line and column are counted from 1.

The document provides the methods TextDocument..::..GetLocation(Int32) and TextDocument..::..GetOffset(TextLocation) to convert between offsets and TextLocations.


If you are working with the text editor, you will likely run into the problem that you need to store an offset, but want it to adjust automatically whenever text is inserted prior to that offset.

Sure, you could listen to the TextDocument.Changed event and call GetNewOffset on the DocumentChangeEventArgs to translate the offset, but that gets tedious; especially when your object is short-lived and you have to deal with deregistering the event handler at the correct point of time.

A text anchor object stores an Offset, but automatically updates the offset when text is inserted/removed before the offset.

A much simpler solution is to use the ICSharpCode.AvalonEdit.Document..::..TextAnchor class. Please take a look at the documentation for that class for more details.


An offset in the document, but relative to the start offset of a VisualLine.

Relative text offsets are used to store document offsets in visual lines.

You can convert between relative text offsets and document offsets by adding/subtracting VisualLine..::..FirstDocumentLine.Offset.


An integer value that specifies a position inside a VisualLine.

Not only text has a length in the visual line, but also other VisualLineElements. VisualColumn is counting from 0 for each visual line.

For example, tab markers take 2 visual columns (the marker and the tab space), newline markers take 1 visual column; folding markers take just 1 visual column even though they are longer in the document text.

Use the VisualLine..::..GetVisualColumn(Int32) and VisualLine..::..GetRelativeOffset(Int32) methods to convert between visual columns and relative text offsets.


Do not confuse VisualColumn with text columns. VisualColumn starts at 0, text column at 1. Text may have different length in the two coordinate systems (e.g. tab markers, foldings).


A Line,Column,VisualColumn triple.

The ICSharpCode.AvalonEdit..::..TextViewPosition struct can be implicitly converted to TextLocation, but has the additional VisualColumn information that is necessary to accurately hold the caret position when VisualLineElements with DocumentLength 0 are in use.


A double value that specifies the distance from the top of the document to the top of a line measured in device-independent pixels.

VisualTop is equivalent to the Y component of a VisualPosition.


A Point value (double X,Y) that specifies the position of an element from the top left document corner measured in device-independent pixels.

To convert a VisualPosition to or from a (mouse) position inside the TextView, simply subtract or add TextView..::..ScrollOffset to it.