In This Article

Selection and Block Selection

SyntaxEditor has a powerful text selection model that supports both continuous stream (snaking) as well as block selection within editor views.

Accessing the Selection

Each IEditorView has its own selection model since the selection is unique to each view. The selection and its functionality described below is available via the IEditorViewSelection interface, which can be retrieved from the IEditorView.Selection property.

The currently active view within a SyntaxEditor is available from the SyntaxEditor.ActiveView property.

Continuous Stream vs. Block Selection

Continuous stream is considered the "normal", snaking type of selection. It has a start and end position and encompasses all text in between the positions.

Block selection, sometimes called column or rectangular selection, allows a singular rectangular portion of text to be selected instead of the whole line. The selection includes all of the characters captured within the rectangle defined by the start (anchor) position and the end position in the selection.


Continuous stream (left) vs. block (right) selection

When a block selection is active, multiple lines can be edited at the same time. Typing will enter the character on each line. Pasting single-line text will paste the text on each line. Likewise, operations like Del and Backspace will work on each line.

Getting Information About the Current Selection

There are a number of properties on the IEditorViewSelection interface that allow you to see exactly what is selected in the selection's owner IEditorView.

Member Description
EndOffset Property Gets or sets the end offset of the primary selection range.
EndPosition Property Gets or sets the TextPosition that represents the end of the primary selection range.
FirstOffset Property Gets the first offset in the primary selection range.
FirstPosition Property Gets the first TextPosition in the primary selection range.
GetTextRanges Method Returns an array of TextRange objects that specify the ranges of text that is selected.
IsNormalized Property Gets whether the primary selection range is normalized (StartPosition occurs at or before the EndPosition).
IsZeroLength Property Gets whether the primary selection range has a zero length.
LastOffset Property Gets the last offset in the primary selection range.
LastPosition Property Gets the last TextPosition in the primary selection range.
Length Property Gets the absolute offset length of the primary selection range.
Mode Property Gets a SelectionModes that indicates the selection mode currently in use.
PositionRange Property Gets or sets the TextPositionRange that describes the start and end TextPosition of the primary selection.
Ranges Property Gets the collection of selection ranges in the view. This collection ordinarily contains a single range, but can have more than one range when there are multiple selections. Each selection range has its own caret at the selection range's end position.
StartOffset Property Gets or sets the start offset of the primary selection range.
StartPosition Property Gets or sets the TextPosition that represents the start of the primary selection range.
TextRange Property Gets or sets the TextRange that specifies the offset range of the primary selection.

Creating Continuous Stream Selections at Run-time

Continuous stream selections can be made via the mouse or the keyboard.

To make a continuous stream selection with the mouse, left click in the text area and drag to create the selection. Hold Ctrl when click+dragging to select by word instead of character, but only if the SyntaxEditor.AreMultipleSelectionRangesEnabled property is false.

To make a continuous stream selection with the keyboard, hold the Shift key, and press any arrow key. Other keys such as Home, End, PageUp, and PageDn also create selections while holding Shift. Holding Ctrl+Shift when using the arrows keys will select by word instead of character.

Creating Multiple Selections at Run-time

Multiple continuous stream selections can be made when the SyntaxEditor.AreMultipleSelectionRangesEnabled property is true, the default.

A new selection can be added by holding the Ctrl key when clicking in the text area or clicking on the selection or line number margins.

Press the Esc key when there are multiple selection ranges to collapse back to a single primary selection range.

Most built-in edit actions and editing features are designed to support multiple selections. For instance, pressing Shift+Right Arrow will extend all of the selections by one character. Copying text from multiple selections unions the selected text, joining each range's text with a line terminator. Pasting multi-line text into a view with the same number of selections as text lines being pasted will replace each selection with a related line from the pasted text.

Creating Block Selections at Run-time

Block selections can be made via the mouse or the keyboard.

To make a block selection with the mouse, hold the Alt key, left click in the text area and drag to create the selection. Hold Ctrl+Alt+Shift when click+dragging to select by word instead of character.

To make a block selection with the keyboard, hold the Shift+Alt keys, and press any arrow key. Holding Ctrl+Alt+Shift when using the arrows keys will select by word instead of character.

Creating a Single Selection Programmatically

The selection can be set programmatically using a number of the properties and methods on IEditorViewSelection, such as StartOffset.

The SelectRange method has several overloads that allow for easy selection creation with options. For instance you can create a selection via an offset/length, a TextRange, a TextPosition pair, or a TextPositionRange. Each overload also has corresponding overloads that accept a SelectionModes parameter. When you use this parameter, you can indicate whether the selection should be a continuous stream or block selection.

When using setter properties or SelectRange method overloads that don't accept a SelectionModes property, the current selection mode (indicated by the Mode property) will be used.

This code selects the text range 0-20 (20 characters) using the current Mode:

editor.ActiveView.Selection.SelectRange(new TextRange(0, 20));

This code selects the text range 10-20 (10 characters) using continuous stream mode:

editor.ActiveView.Selection.SelectRange(10, 10, SelectionModes.ContinuousStream));

This code selects the text position (line, char) range (1,0)-(2,10) using block mode:

editor.ActiveView.Selection.SelectRange(new TextPositionRange(1, 0, 2, 10), SelectionModes.Block);

The IEditorViewSelection interface provides a lot of additional methods for performing relative selection operations such as MoveDown, SelectPageDown, SelectBlockRight, etc. Check the IEditorViewSelection class library member list to see the numerous methods that are available.

Creating Multiple Selections Programmatically

The IEditorViewSelection.SelectRanges method allows for a collection of TextPositionRange objects to be specified that will become multiple selections. A caret will be placed at the end of each position range. An optional second parameter allows the index of the primary selection range to be specified. If Esc is pressed by the end user, all selection ranges but the primary selection range will be removed.

Getting or Replacing the Selected Text

The IEditorView.SelectedText property gets and sets the currently selected text and pays proper attention to block selections if applicable. The setter calls the ReplaceSelectedText method.

This code puts the currently selected text in a string:

string text = editor.ActiveView.SelectedText;

For setting text, the ReplaceSelectedText method can be called to replace the currently selected text with alternate text. The DeleteSelectedText method can be called to delete the currently selected text.

This code deletes currently selected text:


This code replaces currently selected text:

editor.ActiveView.ReplaceSelectedText(TextChangeTypes.Typing, "Inserted Text");

Both these methods have overloads that accept an IEditorViewTextChangeOptions object, which inherits ITextChangeOptions. The base options in ITextChangeOptions are described in the Text Changes and Operations topic. The IEditorViewTextChangeOptions interface defines several additional properties.

The IsBlock option indicates if the text change should be considered a block text change. The SelectInsertedText option determines if the inserted text should be selected. The VirtualCharacterFill option determines if when the caret is at a virtual character position, the text change will insert whitespace into the document to fill up to the insertion point's TextPosition.

Determining If Any of the Selected Text is Read-Only

The IEditorViewSelection.IsReadOnly property returns whether any of the text in the selection is currently flagged as read-only.

Disabling Certain Selection Modes

The SyntaxEditor.SelectionModesAllowed property is a flags enumeration that indicates the types of selection modes that are permitted.

By altering the SelectionModes value set to this property, you can determine whether continuous stream and block selections are allowed. The default is to allow both.

Selection Change Event

The SyntaxEditor.ViewSelectionChanged event fires whenever the selection's anchor or length have changed. This makes the event an ideal place to update the current caret column and position in a status bar.

The event passes an EditorViewSelectionEventArgs that has a number of useful properties on it. It tells you the IEditorView that contains the selection (be sure to only update UI when the view's IsActive property is true). The CaretPosition property contains the primary caret's TextPosition. Use its DisplayLine and DisplayCharacter properties when displaying the caret location in a status bar or other user interface.

Batch Selection Changes

Sometimes multiple selection changes might be made, such as in the case of performing a text change that alters the selection, but wanting to specifically set another selection right afterward. In this scenario, a batch can be created to wrap the text change and any selection changes. The selection changed event will only be raised when the outermost batch is completed.

This example shows how to create a disposable batch object. When the batch is disposed, the batch is completed.

using (var batch = editor.ActiveView.Selection.CreateBatch(EditorViewSelectionBatchOptions.None)) {
	// Perform text changes and selection changes here

Capturing and Restoring the Selection State

Sometimes it's handy to be able to capture and later restore a selection. This feature is used in actions like indent lines where the text in the selection is modified and when complete, the selection still appears to contain the same relative range of text, even though new characters were inserted within the selected text range.

The IEditorViewSelection.CaptureState method can be called to return an IEditorViewSelectionState object. This object persists information about the current selection state. If you make changes and then call the IEditorViewSelectionState.Restore method, the selection will attempt to restore itself as best it can to the text that was originally selected.

This functionality makes use of the snapshot translation feature, found in the text framework.

Selection Collapsing

The Esc key can be pressed to collapse the selection.

If there are multiple selection ranges, the Esc key will first remove all selections other than the primary selection.

When there is a single selection range, the selection will collapse to the caret, meaning make the selection go to zero-length. This behavior can be changed so that the selection collapses to the selection anchor instead. The SyntaxEditor.SelectionCollapsesToAnchor property can be set to true to activate this behavior.

Some end users like the ability to auto-collapse the selection when a copy operation occurs. Set the SyntaxEditor.SelectionCollapsesOnCopy property to true to enable this behavior.

Selection Grippers for Touch

When the end user touches a view, a small selection gripper will appear below the start and end of the selection. The gripper can be dragged to resize the selection, or tapped to show a context menu.

The SyntaxEditor.AreSelectionGrippersEnabled property can be set to false to disable display of the selection grippers.

Virtual Space

The SyntaxEditor.IsVirtualSpaceAtLineEndEnabled property can be set to true to allow virtual space at the end of view lines.

This feature permits the caret is able to move beyond a view line's line terminator. Typing a character while the caret is in virtual space past the end of a line will automatically insert enough whitespace characters to fill up to the typed character before it is inserted.

Block selections can be made in virtual space at the end of lines, even without line end virtual space being enabled. This prevents the caret from snapping to an offset when making a block selection, which can sometimes be problematic.