Как отключить события клавиатуры и мыши в части визуального дерева без использования IsEnabled?

У меня есть требование для создания псевдомодальных диалогов в WPF. То есть, по некоторым специфическим (техническим) причинам программное обеспечение не может порождать модальные диалоги. Вместо этого пользователь должен взаимодействовать со "встроенными" модальными диалогами, когда это необходимо.

Я нашел решение, которое очень хорошо работает с MVVM и заботится о Dispatcher и синхронном характере модальных диалогов. Однако я столкнулся с проблемой отключения пользовательского ввода в фоновом графическом интерфейсе. Установка для всех элементов управления значения IsEnabled = false, к сожалению, неприемлема, поскольку она изменяет визуальное состояние фоновых элементов управления (оттенки серого -> плохая читаемость).

Есть ли прямой способ отключить пользовательский ввод (включая фокус и клавиатуру) в фоновом режиме без изменения визуального состояния?

Спасибо за вашу помощь!

4 ответа

Решение

У меня есть проект на GitHub, который предоставляет кастом FrameworkElement это позволяет отображать модальное содержимое поверх основного содержимого.

Элемент управления можно использовать так:

<c:ModalContentPresenter IsModal="{Binding DialogIsVisible}">
    <TabControl Margin="5">
            <Button Margin="55"
                    Padding="10"
                    Command="{Binding ShowModalContentCommand}">
                This is the primary Content
            </Button>
        </TabItem>
    </TabControl>

    <c:ModalContentPresenter.ModalContent>
        <Button Margin="75"
                Padding="50"
                Command="{Binding HideModalContentCommand}">
            This is the modal content
        </Button>
    </c:ModalContentPresenter.ModalContent>

</c:ModalContentPresenter>

Особенности:

  • Отображает произвольный контент.
  • Не отключает основной контент, пока отображается модальный контент.
  • Отключает доступ с помощью мыши и клавиатуры к основному содержимому, пока отображается модальное содержимое.
  • Является модальным только для содержимого, которое оно охватывает, а не для всего приложения.
  • может быть использован в дружественном для MVVM виде путем привязки к IsModal имущество.

Вы можете установить .IsHitTestVisible свойство, чтобы отключить любые щелчки мыши для этого элемента управления / окна. Это работает так же, как настройки .IsEnabled, но без изменения визуального состояния (серые элементы управления).

Я боролся с той же проблемой (также MVVM). Я также использую оверлей UserControl вместо модального всплывающего окна. (В моем случае мне не нравится IsEnabled=false не из-за отключенного стиля, а потому, что переключение IsEnabled затрудняет возврат фокуса клавиатуры.)

Я использую решение наложения (выше) для блокировки действий мыши. И для "другой половины решения" - отключение ввода с клавиатуры - я передаю это в главном окне:

Окно
+----------------+  private void Window_PreviewKeyDown(отправитель объекта,
|                |                                     KeyEventArgs e){
| Прозрачный |      if (this.myDialog.Visibility == Visibility.Visible){
|                |          e.Handled = true;
|  +----------+  |      }
|  | myDialog |  |  }
|  | содержание | |
| + ---------- + |
| |
+ ---------------- +

Частичное решение может заключаться в том, чтобы ваш "диалоговый" элемент управления покрывал все окно вашего приложения, но большая его часть была бы прозрачной, с непрозрачным содержимым диалога в середине, например:

+----------------+
|                |
|  Transparent   |
|                |
|  +----------+  |
|  | dialog   |  |
|  | content  |  |
|  +----------+  |
|                |
+----------------+

Но это немного взломать.

Чтобы напрямую ответить на ваш вопрос, вы можете использовать Trigger для свойства IsEnabled в ваших элементах управления, чтобы не изменять цвета. Возможно, кто-то с Visual Studio на своем поле может предоставить пример кода.:)

Ответ на ваш комментарий:

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

Другие вопросы по тегам