问题
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 ?
回答1:
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;
}
回答2:
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;
};
}
回答3:
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).
来源:https://stackoverflow.com/questions/32770422/uwp-messagedialog-crashes-the-app-on-windows-phone-and-tablet-mode