UWP - MessageDialog отключает приложение в режиме Windows Phone и планшета

В приложении Windows 10 Universal я хочу отображать MessageDialog при нажатии кнопки "Назад".

Код моей страницы следующий:

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();
 }

Когда я использую приложение в "локальной машине", диалог хорошо отображается. Но когда я превращаю Windows в "планшетный режим", или когда я пытаюсь использовать ее на своем Windows-телефоне, метод ShowAsync приводит к сбою приложения (без ошибок).

Почему приложение сбой?

3 ответа

Проблема заключается в том, что метод "dialog.ShowAsync()" должен вызываться из потока пользовательского интерфейса.

Вот как я это решил:

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


Вы должны обрабатывать 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();
 }

Вы должны добавить onnavigatedfrom метод, чтобы отменить регистрацию события, иначе он будет срабатывать дважды!

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


Невозможно выполнить то, что вы хотите - обработчик back key требует немедленного ответа (обработанного или нет), но диалог по сути является асинхронным.

Вы можете, конечно, выбрать, чтобы отметить событие как Handled, прежде чем вы откроете диалоговое окно, но затем, если пользователь скажет "Да", вы не сможете перейти от него. Вы можете, конечно, закрыть приложение, но это плохая идея (см. Последний абзац)

Тем не менее, вам обычно не требуется это диалоговое окно, потому что в Windows 10 поддержка приложения не прерывает его, он просто переключается на предыдущее приложение (или в меню "Пуск" ). Пользователь может тривиально вернуться к нему с помощью переключателя задач (или снова запустить его).

licensed under cc by-sa 3.0 with attribution.