Keyboard Shortcuts
Which keys does the WPF TextControl understand before your application adds any? The tables below answer the question for moving the caret, editing, hyphens and tables, so that you can document them for your users and avoid them when you add shortcuts of your own. The last sections add such shortcuts in a KeyDown handler and give Enter a new meaning in a PreviewKeyDown handler.
Mouse actions, such as a triple-click to select a paragraph, are listed on Selections and Caret Position.
Move the Caret
| Keys | Action |
|---|---|
| Left Arrow, Right Arrow | Moves the caret one character to the left or right |
| Up Arrow, Down Arrow | Moves the caret one line up or down |
| Ctrl+Left Arrow | Moves the caret to the beginning of the current word |
| Ctrl+Right Arrow | Moves the caret to the beginning of the next word |
| Home | Moves the caret to the beginning of the line |
| End | Moves the caret to the end of the line |
| Ctrl+Home | Moves the caret to the start of the text |
| Ctrl+End | Moves the caret to the end of the text |
| Page Up, Page Down | Scrolls up or down by the height of the visible area minus one line, if there is a vertical scroll bar |
| Shift+Page Up, Shift+Page Down | Scrolls the document horizontally |
| Ctrl+Page Up, Ctrl+Page Down | Zooms the document in or out |
With Shift held down, every key that moves the caret extends the selection to the new position. Shift+End, for example, selects the rest of the line.
Edit Text
| Keys | Action |
|---|---|
| Shift+Enter | Inserts a line break without starting a new paragraph |
| Ctrl+Enter | Inserts a page break |
| Ctrl+Shift+Enter | Inserts a column break, so that the text continues in the next column of a multi-column section |
| Ctrl+Shift+Spacebar | Inserts a non-breaking space |
| Delete | Deletes the selected text |
| Ctrl+Backspace, Shift+Backspace | Deletes the previous word |
| Ctrl+C | Copies the selected text to the clipboard |
| Ctrl+X | Copies the selected text to the clipboard and deletes it |
| Ctrl+V | Pastes the content of the clipboard in place of the selection |
| Ctrl+Z | Undoes the last action |
| Ctrl+Y | Restores the last undone action |
The methods behind the clipboard and undo keys are described on Clipboard Operations and Undo and Redo.
Insert Hyphens and Dashes
| Keys | Inserts | Word may be divided there |
|---|---|---|
| Hyphen (-) | A hyphen or minus sign | Yes |
| Ctrl+Hyphen | An end-of-line hyphen, which is not visible unless the word is divided at that point | Yes |
| Ctrl+Shift+Hyphen | A hyphen for compound words that keeps the parts on one line | No |
| Ctrl+Minus on the numeric keypad | An en dash | Yes |
| Ctrl+Alt+Minus on the numeric keypad | An em dash | Yes |
For automatic hyphenation, see Spell Checking and Hyphenation.
Keys in Tables
| Keys | Action |
|---|---|
| Tab | Selects the next table cell. In the last cell of a table, it adds a new row at the end of the table. |
| Shift+Tab | Selects the previous table cell |
| Ctrl+Tab | Inserts a tab character in the cell |
| Enter | At the first input position of a document that begins with a table, inserts an empty line in front of the table |
Outside of tables, the dependency property AcceptsTab decides what Tab does: with true, it types a tab character; with false, it moves the keyboard focus to the next control of the window. Set it in XAML with AcceptsTab="True".
Form fields have keys of their own, such as the Spacebar to check a check box or open a drop-down list. They are listed on Form Fields and Conditional Instructions.
Add Your Own Shortcuts
Key presses raise the KeyDown routed event of the control. A handler checks the key and the modifier keys, calls a method of the editor and sets e.Handled so that the editor ignores the key. Connect the handler in MainWindow.xaml:
<Window x:Class="SampleApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WPF="clr-namespace:TXTextControl.WPF;assembly=TXTextControl.WPF"
Title="MainWindow" Height="450" Width="800">
<Grid>
<WPF:TextControl x:Name="textControl1" KeyDown="TextControl1_KeyDown" />
</Grid>
</Window>
The handler in MainWindow.xaml.cs opens the Find and Replace dialog boxes with Ctrl+F and Ctrl+H, selects all text with Ctrl+A and switches between insert and overwrite mode with the Insert key. Replace SampleApp with the namespace of your project:
using System.Windows;
using System.Windows.Input;
using TXTextControl;
namespace SampleApp;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void TextControl1_KeyDown(object sender, KeyEventArgs e)
{
bool ctrlOnly = Keyboard.Modifiers == ModifierKeys.Control;
// Ctrl+F: open the built-in Find dialog box
if (ctrlOnly && e.Key == Key.F)
{
textControl1.Find();
e.Handled = true;
}
// Ctrl+H: open the built-in Replace dialog box
else if (ctrlOnly && e.Key == Key.H)
{
textControl1.Replace();
e.Handled = true;
}
// Ctrl+A: select the whole text
else if (ctrlOnly && e.Key == Key.A)
{
textControl1.SelectAll();
e.Handled = true;
}
// Insert: switch between inserting and overwriting text
else if (Keyboard.Modifiers == ModifierKeys.None && e.Key == Key.Insert)
{
textControl1.InsertionMode = textControl1.InsertionMode == InsertionMode.Insert
? InsertionMode.Overwrite
: InsertionMode.Insert;
e.Handled = true;
}
}
}
Run the application and press Ctrl+H: the Replace dialog box opens.
The code works as follows:
Keyboard.ModifiersofSystem.Windows.Inputreturns the modifier keys held down. Comparing it withModifierKeys.Controlaccepts Ctrl alone, so that Ctrl+Shift+F doesn't trigger the command.e.Keyis the pressed key.- Find and Replace without parameters open the built-in dialog boxes. SelectAll selects the whole text.
- InsertionMode is
Insertwhen typed text is inserted andOverwritewhen it replaces the text at the input position. e.Handled = truemarks the routed event as handled.
The TX Words sample of the setup handles Ctrl+O, Ctrl+S and Ctrl+P for opening, saving and printing in the same kind of handler. It is installed in %USERPROFILE%\Documents\TX Text Control 34.0.NET for WPF\CSharp\TX Words\Shortcuts.
Insert a Line Break Instead of a Paragraph on Enter
Some applications, such as an editor for address blocks or table captions, need Enter to start a new line inside the same paragraph, the way Shift+Enter does. In code, a line break is the vertical tab character, written "\v" in C#: assigning it to Selection.Text inserts a line break at the input position.
Enter is a key the editor handles itself, and that changes which event you use. WPF raises the tunneling PreviewKeyDown event before the bubbling KeyDown event. According to Microsoft's input overview for WPF, a control that handles a key gets it before the KeyDown handlers of the application, which are called only for keys the control left unhandled; a PreviewKeyDown handler is called first. For keys that have a built-in function, handle PreviewKeyDown, as the handler below does. Connect it in MainWindow.xaml with PreviewKeyDown="TextControl1_PreviewKeyDown" on the TextControl element:
private void TextControl1_PreviewKeyDown(object sender, KeyEventArgs e)
{
// Enter without modifier keys: insert a line break, not a new paragraph
if (e.Key == Key.Enter && Keyboard.Modifiers == ModifierKeys.None)
{
textControl1.Selection.Text = "\v";
e.Handled = true;
}
}
The code works as follows:
Key.EnterwithModifierKeys.Nonelimits the change to Enter alone, so Ctrl+Enter still inserts a page break and Ctrl+Shift+Enter a column break.Selection.Text = "\v"replaces the selected text, if there is any, with a line break.e.Handled = truemarks the event as handled, so that neither the editor nor aKeyDownhandler inserts a paragraph as well.
The old Windows Forms version of this sample used the KeyPress event, which the WPF TextControl does not have. Microsoft describes the order of the keyboard events in the Input Overview of WPF.
Next Steps
- Selections and Caret Position: the mouse actions and the selection in code.
- Search and Replace: the Find and Replace dialog boxes and sidebars.
- Events: the other events of the editor.