Ключ доступа выбирается, даже если мы не нажимаем клавишу Alt в WPF - PullRequest
4 голосов
/ 09 декабря 2011

У меня есть приложение WPF с панелью инструментов. В панели инструментов у меня есть несколько пользовательских элементов управления в качестве инструментов.

Я установил ключ доступа для каждого элемента управления, он работает нормально.

Проблема заключается в следующем: если я щелкаю пользовательский элемент управления (который состоит из кнопки и метки, я установил ключ доступа для кнопки), заданная задача завершается, но когда я нажимаю любую клавишу доступа без нажатия клавиши «Alt», оно выбирается.

Есть идеи?

Ответы [ 3 ]

3 голосов
/ 18 апреля 2013

Очевидно, это было преднамеренное изменение Microsoft.См. Ответ Атанаса Коральского здесь:

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

Мнемоники меню и панели инструментов работают без нажатия клавиши Alt.Мы решили, что у нас будет одинаковое поведение во всех случаях, поэтому доступ к клавише работает без нажатия клавиши Alt.

Я понимаю, что это не соответствует формам, и мы рассмотрим эту проблему и изменим поведение в следующей версии..

Пока что в качестве обходного пути вы можете зарегистрировать обработчик класса для всех событий AccessKeyPressed и обработать событие, если клавиша Alt не нажата.

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;
        }
    }
}

Также см. Ответ mfc2wpf:

Я использовал выше, и это работает.Однако это предотвратило действие по умолчанию для Enter и ESC.Поэтому я вставил следующее в начало метода:

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

Ключи доступа включают Enter и Esc , которые являются ключами по умолчанию для Button с IsDefault = true или IsCancel = true.Если вы не хотите требовать Alt + Введите и Alt + Esc для этих кнопок, вам необходимо добавить специальныесостояние для обработчика.

2 голосов
/ 25 апреля 2015

Начиная с .Net 4.5 вы можете настроить это поведение с помощью свойства CoreCompatibilityPreferences.IsAltKeyRequiredInAccessKeyDefaultScope .Чтобы изменить поведение клавиш доступа таким образом, чтобы они срабатывали только при нажатии Alt, установите для него значение true.

CoreCompatibilityPreferences.IsAltKeyRequiredInAccessKeyDefaultScope = true;

Как указано в документации, это должно произойти в самом начале приложения.Установка этого параметра вызовет исключение после его прочтения.

0 голосов
/ 12 октября 2015

Как указано в других ответах, настройка IsAltKeyRequiredInAccessKeyDefaultScope позволяет избежать вызова действий для клавиш доступа без нажатия клавиши Alt .Однако это также может привести к отключению клавиши Enter (для вызова действия по умолчанию) и клавиши Esc (для вызова действия Cancel).

Использованиевместо этого предложенный обходной путь и проверка на Key.Enter и Key.Escape могут обойти эту проблему.Однако вы можете обнаружить, что пункты меню не могут быть выбраны их клавишей доступа без нажатия клавиши Alt , что может быть проблемой, если кнопка в области видимости использует ту же клавишу доступа.

Тогда альтернативой может быть обработка события ключа доступа путем проверки, находится ли потенциально вызываемый элемент управления AccessText в пределах MenuItem или нет, что-то вроде этого:

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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...