|
| 1 | +--- |
| 2 | +title: "Keyboard accelerators" |
| 3 | +description: "Learn how to define keyboard accelerators on Mac Catalyst and Windows so that menu items can be invoked through keyboard shortcuts." |
| 4 | +ms.date: 10/25/2023 |
| 5 | +monikerRange: ">=net-maui-8.0" |
| 6 | +--- |
| 7 | + |
| 8 | +# Keyboard accelerators |
| 9 | + |
| 10 | +Keyboard accelerators are keyboard shortcuts that improve the usability and accessibility of your .NET Multi-platform App UI (.NET MAUI) apps on Mac Catalyst and Windows by providing an intuitive way for users to invoke common actions or commands without navigating the app UI directly. |
| 11 | + |
| 12 | +A keyboard accelerator is composed of two components: |
| 13 | + |
| 14 | +- Modifiers, which include Shift, Ctrl, and Alt. |
| 15 | +- Keys, which include alphanumeric keys, and special keys. |
| 16 | + |
| 17 | +In .NET MAUI, keyboard accelerators are associated with commands exposed in menus, and should be specified with the menu item. Specifically, .NET MAUI keyboard accelerators can be attached to menu items in the menu bar on Mac Catalyst and Windows, and menu items in context menus on Windows. For more information about menu bars, see [Display a menu bar in a .NET MAUI desktop app](menu-bar.md). For more information about context menus, see [Display a context menu in a .NET MAUI desktop app](context-menu.md). |
| 18 | + |
| 19 | +The following screenshots show menu bar items and context menu items that include keyboard accelerators: |
| 20 | + |
| 21 | +:::image type="content" source="media/keyboard-accelerators/menubar.png" alt-text="Screenshot of menu bar items that include keyboard accelerators."::: |
| 22 | +:::image type="content" source="media/keyboard-accelerators/context-menu.png" alt-text="Screenshot of context menu items that include keyboard accelerators."::: |
| 23 | + |
| 24 | +A keyboard accelerator is represented by the `KeyboardAccelerator` class, which represents a shortcut key for a <xref:Microsoft.Maui.Controls.MenuFlyoutItem>. The `KeyboardAccelerator` class defines the following properties: |
| 25 | + |
| 26 | +- `Modifiers`, of type `KeyboardAcceleratorModifiers`, which represents the modifier value, such as Ctrl or Shift, for the keyboard shortcut. |
| 27 | +- `Key`, of type `string?`, which represents the key value for the keyboard shortcut. |
| 28 | + |
| 29 | +These properties are backed by <xref:Microsoft.Maui.Controls.BindableProperty> objects, which means that they can be targets of data bindings. |
| 30 | + |
| 31 | +The `KeyboardAcceleratorModifiers` enumeration defines the following members that be used as values for the `Modifiers` property: |
| 32 | + |
| 33 | +- `None`, which indicates no modifier. |
| 34 | +- `Shift`, which indicates the Shift modifier on Mac Catalyst and Windows. |
| 35 | +- `Ctrl`, which indicates the Control modifier on Mac Catalyst and Windows. |
| 36 | +- `Alt`, which indicates the Option modifier on Mac Catalyst, and the Menu modifier on Windows. |
| 37 | +- `Cmd`, which indicates the Command modifier on Mac Catalyst. |
| 38 | +- `Windows`, which indicates the Windows modifier on Windows. |
| 39 | + |
| 40 | +> [!IMPORTANT] |
| 41 | +> Keyboard accelerators can be attached to <xref:Microsoft.Maui.Controls.MenuFlyoutItem> objects in a <xref:Microsoft.Maui.Controls.MenuBarItem> on Mac Catalyst and Windows, and in a <xref:Microsoft.Maui.Controls.MenuFlyout> on Windows. |
| 42 | +
|
| 43 | +<!-- Mac Catalyst support for keyboard accelerators in context menu items is pending. --> |
| 44 | + |
| 45 | +The following table outlines the keyboard accelerator formats .NET MAUI supports: |
| 46 | + |
| 47 | +| Platform | Single key | Multi-key | |
| 48 | +| -------- | ---------- | --------- | |
| 49 | +| Mac Catalyst | Keyboard accelerators without a modifier, with a single key. For example, using the F1 key to invoke the action associated with a menu item. | Keyboard accelerators with one or more modifiers, with a single key. For example, using CMD+SHIFT+S or CMD+S to invoke the action associated with a menu item. | |
| 50 | +| Windows | Keyboard accelerators with and without a modifier, with a single key. For example, using the F1 key to invoke the action associated with a menu item. | Keyboard accelerators with one or more modifiers, with a single key. For example, using CTRL+SHIFT+F or CTRL+F to invoke the action associated with a menu item. | |
| 51 | + |
| 52 | +## Create a keyboard accelerator |
| 53 | + |
| 54 | +A `KeyboardAccelerator` can be attached to a <xref:Microsoft.Maui.Controls.MenuFlyoutItem> by adding it to its `KeyboardAccelerators` collection: |
| 55 | + |
| 56 | +<!-- TODO: Why is KeyboardAccelerators a collection? Multiple allowed but only first executed on MacCat, but both executed on Win --> |
| 57 | + |
| 58 | +```xaml |
| 59 | +<MenuFlyoutItem Text="Cut" |
| 60 | + Clicked="OnCutMenuFlyoutItemClicked"> |
| 61 | + <MenuFlyoutItem.KeyboardAccelerators> |
| 62 | + <KeyboardAccelerator Modifiers="Ctrl" |
| 63 | + Key="X" /> |
| 64 | + </MenuFlyoutItem.KeyboardAccelerators> |
| 65 | +</MenuFlyoutItem> |
| 66 | +``` |
| 67 | + |
| 68 | +Keyboard accelerators can also be specified in code: |
| 69 | + |
| 70 | +```csharp |
| 71 | +cutMenuFlyoutItem.KeyboardAccelerators.Add(new KeyboardAccelerator |
| 72 | +{ |
| 73 | + Modifiers = KeyboardAcceleratorModifiers.Ctrl, |
| 74 | + Key = "X" |
| 75 | +}); |
| 76 | +``` |
| 77 | + |
| 78 | +When a keyboard accelerator modifier and key is pressed, the action associated with the <xref:Microsoft.Maui.Controls.MenuFlyoutItem> is invoked. |
| 79 | + |
| 80 | +> [!IMPORTANT] |
| 81 | +> While multiple `KeyboardAccelerator` objects can be added to the `MenuFlyoutItem.KeyboardAccelerators` collection, only the first `KeyboardAccelerator` in the collection will have its shortcut displayed on the <xref:Microsoft.Maui.Controls.MenuFlyoutItem>. In addition, on Mac Catalyst, only the keyboard shortcut for the first `KeyboardAccelerator` in the collection will cause the action associated with the <xref:Microsoft.Maui.Controls.MenuFlyoutItem> to be invoked. However, on Windows, the keyboard shortcuts for all of the `KeyboardAccelerator` objects in the `MenuFlyoutItem.KeyboardAccelerators` collection will cause the <xref:Microsoft.Maui.Controls.MenuFlyoutItem> action to be invoked. |
| 82 | +
|
| 83 | +### Specify multiple modifiers |
| 84 | + |
| 85 | +Multiple modifiers can be specified on a `KeyboardAccelerator` on both platforms: |
| 86 | + |
| 87 | +```xaml |
| 88 | +<MenuFlyoutItem Text="Refresh" |
| 89 | + Command="{Binding RefreshCommand}"> |
| 90 | + <MenuFlyoutItem.KeyboardAccelerators> |
| 91 | + <KeyboardAccelerator Modifiers="Shift,Ctrl" |
| 92 | + Key="R" /> |
| 93 | + </MenuFlyoutItem.KeyboardAccelerators> |
| 94 | +</MenuFlyoutItem> |
| 95 | +``` |
| 96 | + |
| 97 | +The equivalent C# code is: |
| 98 | + |
| 99 | +```csharp |
| 100 | +refreshMenuFlyoutItem.KeyboardAccelerators.Add(new KeyboardAccelerator |
| 101 | +{ |
| 102 | + Modifiers = KeyboardAcceleratorModifiers.Shift | KeyboardAcceleratorModifiers.Ctrl, |
| 103 | + Key = "R" |
| 104 | +}); |
| 105 | +``` |
| 106 | + |
| 107 | +## Specify keyboard accelerators per platform |
| 108 | + |
| 109 | +Different keyboard accelerator modifiers and keys can be specified per platform in XAML with the [`OnPlatform`](xref:Microsoft.Maui.Controls.Xaml.OnPlatformExtension) markup extension: |
| 110 | + |
| 111 | +```xaml |
| 112 | +<MenuFlyoutItem Text="Change Theme" |
| 113 | + Command="{Binding ChangeThemeCommand}"> |
| 114 | + <MenuFlyoutItem.KeyboardAccelerators> |
| 115 | + <KeyboardAccelerator Modifiers="{OnPlatform MacCatalyst=Cmd, WinUI=Windows}" |
| 116 | + Key="{OnPlatform MacCatalyst=T, WinUI=C}" /> |
| 117 | + </MenuFlyoutItem.KeyboardAccelerators> |
| 118 | +</MenuFlyoutItem> |
| 119 | +``` |
| 120 | + |
| 121 | +The equivalent C# code is: |
| 122 | + |
| 123 | +```csharp |
| 124 | +KeyboardAcceleratorModifiers modifier = KeyboardAcceleratorModifiers.None; |
| 125 | +string key = string.Empty; |
| 126 | + |
| 127 | +if (DeviceInfo.Current.Platform == DevicePlatform.MacCatalyst) |
| 128 | +{ |
| 129 | + modifier = KeyboardAcceleratorModifiers.Cmd; |
| 130 | + key = "T"; |
| 131 | +} |
| 132 | +else if (DeviceInfo.Current.Platform == DevicePlatform.WinUI) |
| 133 | +{ |
| 134 | + modifier = KeyboardAcceleratorModifiers.Windows; |
| 135 | + key = "C"; |
| 136 | +} |
| 137 | + |
| 138 | +myMenuFlyoutItem.KeyboardAccelerators.Add(new KeyboardAccelerator |
| 139 | +{ |
| 140 | + Modifiers = modifier, |
| 141 | + Key = key |
| 142 | +}); |
| 143 | +``` |
| 144 | + |
| 145 | +## Use special keys in a keyboard accelerator |
| 146 | + |
| 147 | +On Windows, special keys can be specified via a string constant or with an integer. For a list of constants and integers, see the table in <xref:Windows.System.VirtualKey>. |
| 148 | + |
| 149 | +> [!NOTE] |
| 150 | +> On Windows, single key accelerators (all alphanumeric and punctuation keys, Delete, F2, Spacebar, Esc, Multimedia Key) and multi-key accelerators (Ctrl+Shift+M) are supported. However, Gamepad virtual keys aren't supported. |
| 151 | +
|
| 152 | +On Mac Catalyst, special keys can be specified via a string constant. For a list of constants that represent the text input strings that correspond to special keys, see [Input strings for special keys](https://developer.apple.com/documentation/uikit/uikeycommand/input_strings_for_special_keys?language=objc) on developer.apple.com. |
| 153 | + |
| 154 | +The following XAML shows an example of defining a keyboard accelerator that uses a special key: |
| 155 | + |
| 156 | +```xaml |
| 157 | +<MenuFlyoutItem Text="Help" |
| 158 | + Command="{Binding HelpCommand}"> |
| 159 | + <MenuFlyoutItem.KeyboardAccelerators> |
| 160 | + <!-- Alternatively, 112 can be used to specify F1 on Windows --> |
| 161 | + <KeyboardAccelerator Modifiers="None" |
| 162 | + Key="{OnPlatform MacCatalyst=UIKeyInputF1, WinUI=F1}" /> |
| 163 | + </MenuFlyoutItem.KeyboardAccelerators> |
| 164 | +</MenuFlyoutItem> |
| 165 | +``` |
| 166 | + |
| 167 | +In this example the keyboard accelerator is the F1 key, which is specified via a constant on both platforms. On Windows, it could also be specified by the integer 112. |
| 168 | + |
| 169 | +## Localize a keyboard acclerator |
| 170 | + |
| 171 | +Keyboard accelerator keys can be localized via a .NET resource file. The localized key can then be retrieved by using the `x:Static` markup extension: |
| 172 | + |
| 173 | +```xaml |
| 174 | +<MenuFlyoutItem Text="Cut" |
| 175 | + Clicked="OnCutMenuFlyoutItemClicked"> |
| 176 | + <MenuFlyoutItem.KeyboardAccelerators> |
| 177 | + <KeyboardAccelerator Modifiers="Ctrl" |
| 178 | + Key="{x:Static local:AppResources.CutAcceleratorKey}" /> |
| 179 | + </MenuFlyoutItem.KeyboardAccelerators> |
| 180 | +</MenuFlyoutItem> |
| 181 | +``` |
| 182 | + |
| 183 | +For more information, see [Localization](~/fundamentals/localization.md). |
| 184 | + |
| 185 | +## Disable a keyboard accelerator |
| 186 | + |
| 187 | +When a <xref:Microsoft.Maui.Controls.MenuFlyoutItem> is disabled, the associated keyboard accelerator is also disabled: |
| 188 | + |
| 189 | +```xaml |
| 190 | +<MenuFlyoutItem Text="Cut" |
| 191 | + Clicked="OnCutMenuFlyoutItemClicked" |
| 192 | + IsEnabled="false"> |
| 193 | + <MenuFlyoutItem.KeyboardAccelerators> |
| 194 | + <KeyboardAccelerator Modifiers="Ctrl" |
| 195 | + Key="X" /> |
| 196 | + </MenuFlyoutItem.KeyboardAccelerators> |
| 197 | +</MenuFlyoutItem> |
| 198 | +``` |
| 199 | + |
| 200 | +In this example, because the `IsEnabled` property of the <xref:Microsoft.Maui.Controls.MenuFlyoutItem> is set to `false`, the associated CTRL+X keyboard accelerator can't be invoked. |
0 commit comments