WPF Показать меню в режиме навигации клавиатуры - PullRequest
1 голос
/ 20 апреля 2019

Предыстория aka My Configuration

Как и у многих, у меня есть приложение, которое имеет меню, прикрепленное к вершине. Я хотел, чтобы это меню было скрыто до тех пор, пока я не нажму клавишу alt, и тогда я смогу перемещаться по этому меню либо с помощью клавиатуры, либо щелкая по элементам MenuItem.

В моей ViewModel я создал логическое свойство с именем ShowMenu, ICommand с именем ShowMenuCommand, которое работает как триггер для ShowMenu и приступило к связыванию данных с привязкой данных. Вы можете увидеть это здесь:

ShowMenuCommand = new RelayCommand(
    _ => ShowMenu = !ShowMenu);

Меню настроено так:

<Menu Name="MainMenu" DockPanel.Dock="Top"
    Visibility="{Binding ShowMenu, Converter={StaticResource BoolToVis}}"
    LostFocus="MainMenu_OnLostFocus">

Я также настроил сочетания клавиш для левой и правой клавиш, которые запускают ShowMenuCommand.

<Window.InputBindings>
    <KeyBinding Key="F1" Command="{Binding AboutCommand}" />
    <KeyBinding Key="LeftAlt" Modifiers="Alt" Command="{Binding ShowMenuCommand}" />
    <KeyBinding Key="RightAlt" Modifiers="Alt" Command="{Binding ShowMenuCommand}" />
</Window.InputBindings>

Это работает точно так, как я настроил его на работу: меню обычно скрыто, но когда я нажимаю alt, оно появляется и позволяет мне перемещаться по пунктам меню, пока я не нажму или не выберу элемент, и он потеряет фокус, LostFocus для обработчика ShowMenu установлено значение false.

Проблема

Сделав это, я, похоже, утратил способность входить в режим навигации по клавиатуре. Для тех, кто не знает, что я имею в виду, обычно, когда вы нажимаете alt в приложении с графическим интерфейсом, определенные символы становятся подчеркнутыми, и вы можете нажимать эти символы на клавиатуре для навигации по интерфейсу пользователя. Я не знаю формального имени для этого, поэтому бонусный балл начисляется любому, кто может предоставить настоящее имя.

Источники для этого далеко

Как сделать строку меню WPF видимой при нажатии клавиши ALT

Связывание клавиш LeftAlt в WPF

Что теперь?

Я искал высоко и низко, ползал по классам клавиатуры и UIElement в надежде найти что-то, чтобы это исправить, и я нашел пару возможных решений. Тем не менее, причина, по которой я прибег к StackOverflow, заключается в том, что я не знаю, как представить свой поиск в Google таким образом, чтобы найти то, что я ищу.

Мои предлагаемые решения следующие:

  1. Измените ShowMenuCommand, чтобы переключить режим навигации клавиатуры в дополнение к изменению видимости.
  2. Удалите мои сочетания клавиш и подключите видимость меню к тому, включен ли режим навигации с помощью клавиатуры.
    • Я думал, что у меня было бы это с UIElement#IsInputMethodEnabled, однако, похоже, это не так. Тем не менее, я не знаю, имеет ли значение какой элемент, который вы выбираете, и я не помню, пытался ли я настроить таргетинг на Меню или Окно.

Если у кого-то еще есть третья идея или, возможно, кто-то знает, что мне не хватает, пожалуйста, дайте мне знать. Скрывать строку меню до тех пор, пока вы не откроете ее с помощью alt, должно быть очень просто, поэтому я не удивлюсь, если что-то упущу.

Дополнительный контекст

Если вы хотите увидеть какой-либо код, окружающий предоставленные фрагменты, вы можете просмотреть исходный код проекта на GitHub.

1 Ответ

1 голос
/ 20 апреля 2019

Итак, после некоторых дополнительных исследований и некоторой помощи от @Vlad, окончательное решение выглядит следующим образом:

  1. Видимость меню привязана к свойству ShowMenu в View Controller.
  2. Окно имеет обработчик событий KeyUp, который отслеживает нажатие клавиши alt.
private void MainWindow_OnKeyUp(object sender, KeyEventArgs e)
{
    if (e.Key == Key.System && (e.SystemKey == Key.LeftAlt || e.SystemKey == Key.RightAlt))
    {
        MainWindowViewModel mwvm = (MainWindowViewModel)DataContext;

        mwvm.ShowMenu = !mwvm.ShowMenu;
    }
}

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

  1. Обрабатывать событие Click в соответствующих пунктах меню, пропуская те, которые являются просто категориями.

Единственное, о чем это не заботится, - когда пользователь уходит из меню. Я попытался прикрепить событие LostFocus к Меню, однако это событие срабатывает при открытии меню, возможно, потому, что фокус убирается из самого Меню и на поставщика ContextMenu или что-то еще, что фактически обрабатывает рисование открытого меню.

Мне нужно провести еще какое-то исследование и очистить код, но вышеупомянутое решение работает относительно хорошо.

Редактировать: Я оставлю этот ответ невыбранным на пару дней, на случай, если у кого-нибудь еще возникнут какие-либо идеи.

Редактировать 2: Я нашел решение для моего использования. Поскольку у меня есть только один элемент меню верхнего уровня в этом меню, я подключил событие MenuItem SubmenuClosed. Когда это происходит (либо из-за того, что пользователь выбирает опцию, либо из-за того, что он щелкает), меню скрывается, если для ShowMenu установлено значение false.

Возможно, это не самое элегантное решение, но оно функциональное. Я позабочусь об этом позже.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...