Choosing a passkey, even we did not press the "Alt" key in WPF

I have a WPF application that has a toolbar. In the toolbar, I have some user controls as tools.

I set the access key to each control, it works fine.

The problem is this: if I press a user control (which consists of a button and a label, I set the access key for the button), this task will be completed, but when I press any access key without pressing the "Alt" key, it is selected.

Any ideas?

+4
source share
3 answers

Apparently, this was a deliberate change by Microsoft. See Atanas Koralski here:

http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/14f6f49f-0027-471b-b68c-e7f6ba012012

The Menu and ToolBar mimics work without pressing the Alt key. We decided that in all cases we will have a uniform behavior, so working with the access key without pressing the Alt key.

I understand that this does not correspond to parity with the Forms, and we will consider this problem and change the behavior in the next version.

As a workaround, you can register a class handler for all AccessKeyPressed events and handle the event if the Alt key is not pressed.

EventManager.RegisterClassHandler(typeof(UIElement), AccessKeyManager.AccessKeyPressedEvent, new AccessKeyPressedEventHandler(OnAccessKeyPressed)); 

...

 private static void OnAccessKeyPressed(object sender, AccessKeyPressedEventArgs e) { if (!e.Handled && e.Scope == null && (e.Target == null || e.Target == label)) { // If Alt key is not pressed - handle the event if ((Keyboard.Modifiers & ModifierKeys.Alt) != ModifierKeys.Alt) { e.Target = null; e.Handled = true; } } } 

Also see mfc2wpf answer:

I used the above and it works. However, this prevented the default action for Enter and ESC. So I inserted the following at the top of the method.

 if (Keyboard.IsKeyDown(Key.Enter) || Keyboard.IsKeyDown(Key.Escape)) return; 

Access keys include Enter and Esc , which are the default keys for Button , which have IsDefault = true or IsCancel = true . If you do not want to require Alt + Enter and Alt + Esc for these buttons, you need to add a special condition to the handler.

+3
source

Starting with .Net 4.5, you can configure this behavior using the CoreCompatibilityPreferences.IsAltKeyRequiredInAccessKeyDefaultScope property. To change the behavior of the passkey so that they work only when Alt is pressed, set to true.

 CoreCompatibilityPreferences.IsAltKeyRequiredInAccessKeyDefaultScope = true; 

As stated in the documentation, this should be at the beginning of the application. After that, it throws an exception after reading it.

+2
source

As indicated in other answers, setting IsAltKeyRequiredInAccessKeyDefaultScope avoids invoking actions for access keys without pressing the Alt key. However, this can also disable the Enter key (to invoke the default action) and the Esc key (to invoke the Cancel action).

Using the proposed workaround instead, and testing for Key.Enter and Key.Escape , can work around this problem. However, you may find that menu items cannot be selected by the access key without pressing the Alt key, which can be a problem if the button in the area uses the same access key.

An alternative would be to access the access key event, checking if the potentially called AccessText control is within the MenuItem or not, something like these lines:

 EventManager.RegisterClassHandler( typeof(UIElement), AccessKeyManager.AccessKeyPressedEvent, new AccessKeyPressedEventHandler(OnAccessKeyPressed)); 

...

 static void OnAccessKeyPressed(object accessKeyTarget, AccessKeyPressedEventArgs e) { if (!e.Handled && e.Scope == null && (Keyboard.Modifiers & ModifierKeys.Alt) != ModifierKeys.Alt && !ShouldElementHandleAccessKeysWhenAltIsNotPressed(accessKeyTarget as UIElement)) { e.Target = null; e.Handled = true; } } static bool ShouldElementHandleAccessKeysWhenAltIsNotPressed(UIElement element) { if (element == null) return false; var accessText = element as AccessText; if (accessText != null && !IsDecendantOfMenuItem(accessText)) return false; return true; } static bool IsDecendantOfMenuItem(DependencyObject element) { for (; element != null; element = VisualTreeHelper.GetParent(element)) if (element is MenuItem) return true; return false; } 
0
source

Source: https://habr.com/ru/post/1385509/


All Articles