Неожиданное поведение System.Windows.Window.ShowDialog(), когда другие окна не открыты. Есть идеи, почему?

Я уловил это (с некоторыми усилиями), когда мое приложение WPF MVVM попыталось отобразить два последовательных диалоговых окна ошибок перед запуском главного окна: после подтверждения первого окна приложение зациклилось, а второе диалоговое окно ошибки так и не появилось. .

Я исправил проблему, но я надеялся, что кто-нибудь может просветить меня, почему это произошло.

Такое впечатление, что если нет немодальных открытых окон, если было закрыто одно диалоговое окно, то все новые диалоговые окна сразу же закрываются, без отображения.

Его очень легко воспроизвести, так что вот очень тщеславный код, чтобы проиллюстрировать проблему. Этот код завершен, поэтому, используя только его, вы сможете воспроизвести его.

Создайте элемент управления Window для диалогового окна без кода и только со следующим кодом XAML:

<Window x:Class="ForumExampleShowDialogIssue.OKDialogWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="OKDialogWindow" Height="300" Width="300">
<StackPanel>
    <TextBlock Text="This is a Window with a single button. The button is set to Cancel, so it closes the window."
               TextWrapping="Wrap"
               Margin="5"/>
    <Button Content="OK" IsCancel="True" IsDefault="True"
            Margin="5"/>
</StackPanel>

Next, use the standard WPF App class, with nothing new in the XAML, but with the following in the code behind:

protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);

    OKDialogWindow alwaysOpen = new OKDialogWindow();
    alwaysOpen.Show();

    while (true)
    {                
        OKDialogWindow dialogWindow = new OKDialogWindow();
        Console.WriteLine("Before show");
        dialogWindow.ShowDialog();
        Console.WriteLine("After show");
    }
}

Удалите MainWindow.XAML, если он существует, и удалите ссылку на него из заголовка App.XAML.

Бегать. (программа, не похожая на Лесную).

Это работает так, как ожидалось. Окно alwaysOpen остается открытым, в то время как один за другим dialogWindow экземпляры появляются в диалоговом режиме, закрываются при нажатии OK, а затем показывают следующее.

ОДНАКО, это прерывается, когда вы меняете OnStartup на следующее:

protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);

    while (true)
    {                
        OKDialogWindow dialogWindow = new OKDialogWindow();
        Console.WriteLine("Before show");
        dialogWindow.ShowDialog();
        Console.WriteLine("After show");
    }

}

Когда нет постоянно открытого окна, работает только первое диалоговое окно. После этого в консоль выводятся бесчисленные сообщения "До показа" и "После показа", но новые диалоговые окна не появляются - они автоматически закрываются, как только отображаются.

Конечно, это не может быть запланированным поведением? Вы получаете тот же результат? Есть идеи, почему это происходит?


person Pieter Müller    schedule 04.08.2011    source источник
comment
Есть ли у конструктора по умолчанию вашего класса App public App() { } вызов this.InitializeComponent();? Поскольку его своевременная инициализация очень важна для последовательных вызовов ShowDialog() для работы... Я предполагаю, что в вашем первом ShowDialog автоматически становится основным окном в контексте приложения, а последующие вызовы ShowDialog не работают, поскольку предполагаемое MainWindow к тому времени закрывается... .   -  person WPF-it    schedule 04.08.2011


Ответы (2)


Это предполагаемое поведение.

  • по умолчанию первым открытым окном является MainWindow.
  • По умолчанию единственным окном в списке становится MainWindow (если необходимо удалить другие окна).
  • Класс приложения предназначен для выхода, если в списке окон нет окон.

Проверьте это: http://www.ageektrapped.com/blog/the-wpf-application-class-overview-and-gotcha/

person loxxy    schedule 04.08.2011
comment
Спасибо, это отличная ссылка. Я предполагаю, что я наивный разработчик, о котором он говорит, потому что именно это я и сделал. - person Pieter Müller; 04.08.2011
comment
Я вспомнил, что читал аналогичный код несколько дней назад. В любом случае, рад, что ссылка помогла. - person loxxy; 04.08.2011

Разрешить

Вы можете перейти к файлу App.xaml и добавить его в корневой узел <Application>:

ShutdownMode="OnExplicitShutdown"

Это означает, что даже когда вы закрываете все окна, приложение продолжает работать до тех пор, пока вы явно не вызовете метод InvokeShutdown(). Значение по умолчанию ShutdownMode равно OnMainWindowClose.

Объяснение

В вашем первом фрагменте вы сначала создаете окно, которое никогда не закрывается. Это MainWindow, и он никогда не закрывается. Таким образом, Application никогда не выключается. Но во втором фрагменте MainWindow — это первое диалоговое окно, которое вы создали. Приложение будет закрыто, как только окно закроется. Ваши другие диалоги никогда не будут отображаться после закрытия Application, верно?

См. MSDN: https://msdn.microsoft.com/en-us/library/system.windows.application.shutdownmode(v=vs.110).aspx.

person walterlv    schedule 13.05.2016