Сегодня одно из наших приложений не прошло сертификацию из-за проблемы, о которой я должен был знать. Несмотря на то, что сценарий, в котором происходит исключение, довольно прост, для правильного решения проблемы нужно немного поработать и немного подумать. Другие записи в блоге были написаны об этой конкретной проблеме, хотя предложенные решения, похоже, не сработали для меня. Позвольте мне сначала показать оригинальный код:
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/