4

On Windows Phone 8.1, how to programmatically dismiss a MessageDialog after the ShowAsync call?

I’ve tried calling IAsyncInfo.Close(), it just throws an InvalidOperationException "An illegal state change was requested".

I’ve tried calling IAsyncInfo.Cancel(). The dialog stays visible, the only result - after I tap the “Close” button, TaskCancelledException is marshaled to the awaiting routine.

Update: exact behavior depends on the sequence of the calls.

  1. If IAsyncOperation.Cancel() is invoked before await theTask - await keyword throws TaskCancelledException at once. However, the dialog stays visible.
  2. If await theTask; is invoked before IAsyncOperation.Cancel(), the dialog stays visible, but unlike #1, await continues waiting for a button to be tapped. Only then a TaskCanceledException is raised.

BTW, my scenario is #2: I need to be able to close message dialogs after some routine is already waiting for its completion.

Soonts
  • 20,079
  • 9
  • 57
  • 130
  • So firstly, this is not the intended use of `MessageDialog`, so it's likely to be unsupported. One thing you could try is manually calling the UICommands you added to the MessageDialog for the buttons, but that may just call the delegated methods. If you are looking for a message popup that doesn't require user interaction (such as "Waiting on xxx..."), then you're not looking for `MessageDialog`. What you want is to create a `Popup`, draw some content, and then close the `Popup` when it's done. You can style it to be similar to the `MessageDialog` if you'd like. – Nate Diamond Jun 14 '14 at 19:28
  • 2
    It may be not intended use, but it's possible in Windows Store WinRT apps, so the obvious question is why isn't it possible to use the same code in Windows Phone WinRT apps. – Igor Ralic Jun 14 '14 at 21:12
  • Because the Windows Phone `MessageDialog` class is likely an interop on top of the Windows Phone Silverlight `MessageBox` class in order to bring parity to the base use case. Recreating the entire WinRT library on Windows Phone would be an incredible undertaking in the time given, especially with so much code already implemented and working fine for its intended purpose. Making a custom dialog is pretty easy and there are plenty of guides for doing it so you will mostly have to just copy-paste them in. – Nate Diamond Jun 14 '14 at 21:19
  • Pressing the back button should close the dialog I think. Maybe there's a way to programmatically do that? But even if this did work, I don't think it would be a good solution. There's probably a better way. – Decade Moon Jun 15 '14 at 00:53

1 Answers1

1

This is how it's done in RT. Save that ShowAsync Task and you can cancel that later.

    private IAsyncOperation<IUICommand> dialogTask;
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        MessageDialog dlg = new MessageDialog("This will close after 5 seconds");
        try
        {
            dialogTask = dlg.ShowAsync();
        }
        catch (TaskCanceledException)
        {
            //this was cancelled
        }

        DispatcherTimer dt = new DispatcherTimer();
        dt.Interval = TimeSpan.FromSeconds(5);
        dt.Tick += dt_Tick;
        dt.Start();
    }

    void dt_Tick(object sender, object e)
    {
        (sender as DispatcherTimer).Stop();
        dialogTask.Cancel();
    }

Notice the ShowAsync() is not awaited. Instead is saved to a task which can be cancelled. Sadly I tried this on WP and it didn't work.

Bryan Stump
  • 1,419
  • 2
  • 17
  • 26
  • Nope, it can't be done. Your code doesn't work - please see the update. Have you seen it working on normal Windows, or on Windows Phone 8.1? – Soonts Jun 23 '14 at 17:23
  • See new code in edit. I just verified this code closes the dialog. – Bryan Stump Jun 23 '14 at 20:39
  • Thanks for your help - however, I need a working solution for Windows Phone 8.1 platform. – Soonts Jun 23 '14 at 22:53