Сегодня одно из наших приложений не прошло сертификацию из-за проблемы, о которой я должен был знать. Несмотря на то, что сценарий, в котором происходит исключение, довольно прост, для правильного решения проблемы нужно немного поработать и немного подумать. Другие записи в блоге были написаны об этой конкретной проблеме, хотя предложенные решения, похоже, не сработали для меня. Позвольте мне сначала показать оригинальный код:
MessageBox и навигация
private void TurnCard_Click(object sender, System.Windows.RoutedEventArgs e) { MessageBoxResult mr = MessageBoxResult.Cancel; if (nrTimesClicked > 2) { mr = MessageBox.Show("Continuing now might confuse you. Try again tomorrow?", "Continuing tomorrow?", MessageBoxButton.OKCancel); } if (mr == MessageBoxResult.OK) { NavigationService.GoBack(); } else { Random r = new Random(); int card = r.Next(cardPages.Length); NavigationService.Navigate(new Uri(cardPages[card], UriKind.Relative)); nrTimesClicked++; } }
Выполнение этого кода и нажав кнопку Пуск на телефоне в то время как
MessageBox это видимые результаты в следующем исключения при работе с отладчиком прилагается (это приводит к завершению работы приложения при работе автономного):
NavigationFailed событие возникает. Это вызвано тем, что MessageBox возвращается при нажатии кнопки «Пуск» телефона с возвращаемым значением
MessageBoxResult.Cancel.
, Поскольку в приведенном выше фрагменте кода кнопка «Отмена» используется для перехода на какую-либо страницу, даже если приложение должно перейти в фоновый режим для отображения начального экрана на телефоне, навигация завершается неудачно. Интересно, что приложение не имеет ни малейшего представления о том, что пользователь нажал кнопку «Пуск» на телефоне. Поэтому для решения этой проблемы требуется некоторое мышление.
Пошаговое выполнение проблемного метода TurnCard_Click показало другое поведение: это по крайней мере прояснило, что действительно вызов службы NavigationService вызвал проблему. Чтобы решить эту проблему, можно защитить вызовы NavigationService, перехватив это конкретное исключение:
Защита метода навигации
private void TurnCard_Click(object sender, System.Windows.RoutedEventArgs e) { MessageBoxResult mr = MessageBoxResult.Cancel; if (nrTimesClicked > 2) { mr = MessageBox.Show("Continuing now might confuse you. Try again tomorrow?", "Continuing tomorrow?", MessageBoxButton.OKCancel); } if (mr == MessageBoxResult.OK) { NavigationService.GoBack(); } else { Random r = new Random(); int card = r.Next(cardPages.Length); try { NavigationService.Navigate(new Uri(cardPages[card], UriKind.Relative)); } catch (InvalidOperationException) { ; } nrTimesClicked++; } }
Это решает проблему, хотя мне не нравится, что возникает исключение в ситуации, в которой операционная система должна каким-то образом предотвращать нас (возможно, возвращая какое-то другое значение, когда MessageBox возвращается без нажатия пользователем одной из его кнопок). ). Если вы хотите иметь немного больше гибкости и не возражаете против кодирования немного больше, есть другое возможное решение. Вместо использования MessageBox вы можете использовать
метод Guide.BeginShowMessageBox , определенный в платформе XNA Framework. Этот метод немного сложнее, но и гораздо более гибок, чем его аналог Silverlight. BeginShowMessageBox является асинхронным, что означает, что вам нужно позаботиться о вызове кода, который должен выполняться в потоке пользовательского интерфейса.
Использование BeginShowMessageBox
private void TurnCard_Click(object sender, System.Windows.RoutedEventArgs e) { if (nrTimesClicked > 2) { ShowContinueMessage(); } else { Random r = new Random(); int card = r.Next(cardPages.Length); nrTimesClicked++; NavigationService.Navigate(new Uri(cardPages[card], UriKind.Relative)); } } private void ShowContinueMessage() { List<string> mbOptions = new List<string>(); mbOptions.Add("OK"); mbOptions.Add("Cancel"); string msg = "Continuing now might confuse you. Try again tomorrow?"; string title = "Continuing tomorrow?"; Guide.BeginShowMessageBox(title, msg, mbOptions, 0, MessageBoxIcon.Alert, EnteredAnswer, null); messageBoxVisible = true; } private void EnteredAnswer(IAsyncResult ar) { int? result = Guide.EndShowMessageBox(ar); if (result != null) { messageBoxVisible = false; } if (result != null && result == 0) { this.Dispatcher.BeginInvoke(delegate { NavigationService.GoBack(); }); } else if (result != null) { Random r = new Random(); int card = r.Next(cardPages.Length); this.Dispatcher.BeginInvoke(delegate { NavigationService.Navigate(new Uri(cardPages[card], UriKind.Relative)); }); } }
Интересный код можно найти в методе EnteredAnswer, где мы получаем ключ, введенный пользователем в окне сообщения. Поскольку
EndShowMessageBox возвращает
обнуляемое целое число, у него есть этот прекрасный способ использования нуля в тех случаях, когда пользователь не нажимал ни одну клавишу (другими словами, например, когда окно сообщения удаляется в результате перехода приложения в фоновый режим). , Так что теперь у нас есть способ определить, можем ли мы перемещаться (результат имеет значение, отличное от нуля). В примере кода также устанавливается логическая переменная
messageBoxVisible , которая используется в сочетании с
MVPLinkExtension для повторного отображения окна сообщения, когда пользователь возвращается в приложение. Надеемся, на этот раз заявка пройдет сертификацию.
Источник:
http://mstruys.com/2012/01/19/messagebox-navigation-and-application-life-cycle/