Статьи

MessageBox, жизненный цикл навигации и приложений

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

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/