简体   繁体   中英

UWP - MessageDialog crashes the app on Windows Phone and tablet mode

In a Windows 10 Universal app, I want to display a MessageDialog when the back button is pressed.

The code of my page is the following :

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);

        SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
        SystemNavigationManager.GetForCurrentView().BackRequested += GamePage_BackRequested;
    }

    private async void GamePage_BackRequested(object sender, BackRequestedEventArgs e)
    {
        var dialog = new Windows.UI.Popups.MessageDialog("Are you sure ?");

        dialog.Commands.Add(new Windows.UI.Popups.UICommand("Yes"));
        dialog.Commands.Add(new Windows.UI.Popups.UICommand("No"));

        var result = await dialog.ShowAsync();
    }

When I lauch the App in "local machine", the dialog is well displayed. But when I turn Windows to "tablet mode", or when i try it on my Windows Phone, the ShowAsync method crashes the App (with no error).

Why is the app crashing ?

The problem seems to be that the "dialog.ShowAsync()" method should be called from the UI thread.

This is how I solved it :

    private void GamePage_BackRequested(object sender, BackRequestedEventArgs e)
    {
        e.Handled = true;
        Frame rootFrame = Window.Current.Content as Frame;            
        if (rootFrame.CanGoBack)
        {
            var d = dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => ShowConfirmationDialog(rootFrame));
        }
    }

    public async void ShowConfirmationDialog(Frame rootFrame)
    {
        var dialog = new Windows.UI.Popups.MessageDialog("Are you sure ?");

        dialog.Commands.Add(new Windows.UI.Popups.UICommand("Yes") { Id = 0 });
        dialog.Commands.Add(new Windows.UI.Popups.UICommand("No") { Id = 1 });

        var result = await dialog.ShowAsync();

        if (result != null && result.Label == "Yes")
        {
            rootFrame.GoBack();
        }
    }

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);
        dispatcher = Windows.UI.Core.CoreWindow.GetForCurrentThread().Dispatcher;

        SystemNavigationManager.GetForCurrentView().BackRequested += GamePage_BackRequested;
    }

    protected override void OnNavigatedFrom(NavigationEventArgs e)
    {
        base.OnNavigatedFrom(e);

        SystemNavigationManager.GetForCurrentView().BackRequested -= GamePage_BackRequested;
    }

You should handle the backrequest ; e.handled = true;

private async void GamePage_BackRequested(object sender, BackRequestedEventArgs e)
        {
            e.handled = true;
            var dialog = new Windows.UI.Popups.MessageDialog("Are you sure ?");

        dialog.Commands.Add(new Windows.UI.Popups.UICommand("Yes"));
        dialog.Commands.Add(new Windows.UI.Popups.UICommand("No"));

        var result = await dialog.ShowAsync();
    }

You should add onnavigatedfrom method to unregister the event, otherwise it will trigger twice !

 protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            if (gb.DetectPlatform() == Platform.WindowsPhone)
                HardwareButtons.BackPressed -= HardwareButtons_BackPressed;
           elde
                SystemNavigationManager.GetForCurrentView().BackRequested -= GamePage_BackRequested;
};
        }

There is no way to accomplish what you want -- the back key handler requires an immediate answer (handled or not) but the dialog is inherently async.

You can of course choose to mark the event as Handled before you show the dialog, but then if the user says "Yes" there's no way you can then navigate away. You can of course terminate the app, but that's a bad idea (see final paragraph)

That said, you don't typically need this dialog because in Windows 10, backing out of an app doesn't terminate it, it just switches to the previous app (or the Start menu). The user can trivially return to it via the task switcher (or launching it again).

My UWP application was crashing when I called MessageDialog.ShowAsync in the Application.UnhandledException event handler and this was the top result when I searched for an answer.

I resolved the issue by setting UnhandledExceptionEventArgs.Handled = true before calling MessageDialog.ShowAsync .

This is well documented in another SO question , but I didn't find that answer until after I figured out the solution because I didn't realize calling the method from Application.UnhandledException was significant.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM