2

I'm displaying ModalDialog using sample code Busy.xaml in Template10 :

    public static void SetBusy(bool busy, string text = null)
    {
        WindowWrapper.Current().Dispatcher.Dispatch(() =>
        {
            var modal = Window.Current.Content as ModalDialog;
            var view = modal.ModalContent as Busy;
            if (view == null)
                modal.ModalContent = view = new Busy();
            modal.IsModal = view.IsBusy = busy;
            view.BusyText = text;
            modal.CanBackButtonDismiss = true;
        });
    }

I can close this dialog by using ALT+Left Arrow, but on most Desktop application pressing ESC key usually will also close popup or dialog.

I try to add code to handle KeyDown on Busy.xaml but this method never executed when I press ESC or any key.

     private void UserControl_KeyDown(object sender, KeyRoutedEventArgs e)
     {
         if (e.Key == VirtualKey.Escape)
         {
             e.Handled = true;
             SetBusy(false);
         }
     }

So, how to make this ModalDialog close when user press ESC key ?

Ask Too Much
  • 627
  • 4
  • 19
  • I have edited my question, thanks. – Ask Too Much Jun 07 '16 at 17:34
  • @AskTooMuch Note to your use-case: beside handling "escape" on the keyboard, you might want to handle the "B" button on XBox controllers, as well as the "hardware back button" on mobile devices like phones and tablets. – Stefan Over Jun 08 '16 at 18:13
  • I have tested, most of those scenario has been handled by Template10, I cannot confirm if it's handle "B" button on XBOX since I don't have XBOX device to test, but thanks to let me know this issue. – Ask Too Much Jun 09 '16 at 13:01
  • Have a look at [this](http://stackoverflow.com/questions/34371280/capture-esc-key-in-usercontrol) post too. It seems an easier solution. – Sapan Ghafuri Oct 02 '16 at 15:44

2 Answers2

3

You have to attach an event handler to the CharacterReceived event of the CoreWindow.

Modify the SetBusy method:

public static void SetBusy(bool busy, string text = null)
{
    WindowWrapper.Current().Dispatcher.Dispatch(() =>
    {
        var modal = Window.Current.Content as ModalDialog;
        var view = modal.ModalContent as Busy;
        if (view == null)
            modal.ModalContent = view = new Busy();
        modal.IsModal = view.IsBusy = busy;
        view.BusyText = text;
        modal.CanBackButtonDismiss = true;

        // Attach to key inputs event
        var coreWindow = Window.Current.CoreWindow;
        coreWindow.CharacterReceived += CoreWindow_CharacterReceived;
    });
}

Where as the CoreWindow_CharacterReceived would look like this:

private static void CoreWindow_CharacterReceived(CoreWindow sender,
                                                 CharacterReceivedEventArgs args)
{
    // KeyCode 27 = Escape key
    if (args.KeyCode != 27) return;

    // Detatch from key inputs event
    var coreWindow = Window.Current.CoreWindow;
    coreWindow.CharacterReceived -= CoreWindow_CharacterReceived;

    // TODO: Go back, close window, confirm, etc.
}
Stefan Over
  • 5,851
  • 2
  • 35
  • 61
0

While the modal is open just use something along this route:

private void Modal_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.Escape)
    {
        this.Close();
    }
}

Another way to address (e.KeyCode==Keys.Escape) is:

(e.KeyChar == (char)27)

or

e.KeyCode==(char)Keys.Escape

For this code to work, you need Form.KeyPreview = true;

For more information on what's above: https://msdn.microsoft.com/en-us/library/system.windows.forms.control.keydown.aspx

I believe that you need to append the CancelButton Property for this to work properly.

(Almost the same approach) I believe this should work nicely as well:

private void HandleEsc(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Escape)
        Close();
}

This is for a console application:

if (Console.ReadKey().Key == ConsoleKey.Escape)
{
    return;
}
LatentDenis
  • 2,839
  • 12
  • 48
  • 99