How to disable keyboard and mouse events in a part of the visual tree without using IsEnabled?

StackOverflow https://stackoverflow.com/questions/1113518

  •  12-09-2019
  •  | 
  •  

Question

I've the requirement to build pseudo-modal dialogs in WPF. That is, for some specific (technical) reasons the software is not allowed to spawn modal dialogs. Instead, the user should interact with "embedded" modal dialogs when necessary.

I found a solution that works pretty well with MVVM and takes care of the Dispatcher and the synchronous character of modal dialogs. However, I am facing a problem with disabling the user input in the background GUI. Setting all controls to IsEnabled = false is unfortunately not acceptable since it changes the visual state of the background controls (shades of grey ->bad readability).

Is there a straight forward way to disable the user input (including focus and keyboard) in the background without changing the visual state?

Thanks for your help!

Was it helpful?

Solution

I have a project on github which provides a custom FrameworkElement that allows you to display modal content over the primary content.

The control can be used like this:

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

Features:

  • Displays arbitrary content.
  • Does not disable the primary content whilst the modal content is being displayed.
  • Disables mouse and keyboard access to the primary content whilst the modal content is displayed.
  • Is only modal to the content it is covering, not the entire application.
  • can be used in an MVVM friendly way by binding to the IsModal property.

OTHER TIPS

You can set the .IsHitTestVisible property to disable any mouseclicks to that control/window. This works the same as settings .IsEnabled, but without the visual state change (grey controls).

I've been struggling with the same issue (also MVVM). I'm also using a UserControl overlay instead of a modal popup. (In my case, I dislike IsEnabled=false not because of the disabled style, but because toggling IsEnabled makes it hard to get keyboard focus back.)

I'm using the overlay solution (above) for blocking mouse action. And for the "other half of the solution" - -disabling keyboard input -- I'm handing this in the main window:

Window
+----------------+  private void Window_PreviewKeyDown(object sender,
|                |                                     KeyEventArgs e){
|  Transparent   |      if (this.myDialog.Visibility == Visibility.Visible){
|                |          e.Handled = true;
|  +----------+  |      }
|  | myDialog |  |  }
|  | content  |  |
|  +----------+  |
|                |
+----------------+

A partial solution could be to make your "dialog" control cover your entire application's Window, but have most of it be transparent, with opaque dialog content in the middle, like:

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

But, that is a bit of a hack.

To directly address your question, you can use a Trigger on the IsEnabled property on your controls to keep the colors from changing. Perhaps someone with Visual Studio on their box can provide a code sample. :)

Response to your comment:

I worry that this answer is getting a bit tricky, but you can set the IsTabStop and Focusable properties to false on your controls to get that behavior.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top