Ответ 1
По умолчанию ShutdownMode приложения WPF является OnLastWindowClose. В вашем коде вы показываете одно окно, а затем закрываете его. Таким образом, последнее окно закрывается, и приложение отключается. Затем при выключении вы показываете другое окно. Поскольку приложение закрывается, окно немедленно закрывается.
Итак, все работает так, как запроектировано и запрограммировано вами.
Однако вы хотите сделать что-то другое: окно, которое вы показываете первым, поскольку единственным окном должно быть "специальное окно", а после его закрытия вы хотите продолжить выполнение, показать свое "главное окно", а затем выйти приложение, когда оно (или все окна, связанные с приложением) закрывается.
Самый простой способ: сначала установите режим выключения на OnExplicitShutdown, затем после показа основного окна установите его в OnLastWindowClose или OnMainWindowClose. В коде:
public static void Main()
{
var app = new App();
app.InitializeComponent();
app.ShutdownMode = ShutdownMode.OnExplicitShutdown;
new DialogWindow().ShowDialog();
var mainWindow = new MainWindow();
app.MainWindow = mainWindow;
app.Run(mainWindow);
// When the window has loaded, it should then set the app.ShutdownMode to what you actually want.
}
EDIT: Я не уверен, что именно вы делаете. Код, который вы указали, не будет компилироваться, так как при правильном использовании класса приложений WPF (с созданием App.xaml как ApplicationDefinition) уже определен метод Main. Если у вас просто есть класс, полученный из приложения, у вас нет метода InitializeComponent(). Единственный способ получить код для компиляции - это вручную изменить действие сборки на страницу. Однако в этом случае Application.Current == app.
Итак, что происходит, это следующее:
- Запускается приложение. Поскольку WPF-приложение пока не создано, Application.Current имеет значение NULL. Это также означает, что ни один диспетчерский цикл не запущен, а сообщения диспетчера не обрабатываются (обратите внимание, что цикл диспетчера также обрабатывает сообщения Windows).
- Создается новый объект App. Так как Application.Current имеет значение null, он устанавливает себя как Application.Current.
- Application.Current.MainWindow имеет значение null и Application.Current.Windows - пустой список.
- Так как ShutdownMode - OnLastWindowClose, после закрытия последнего окна текущего приложения (например, приложения) завершается выключение.
- Диалоговое окно отображается модально. Так как никакой диспетчер-цикл не запущен, сам ShowDialog() запускает "локальный" диспетчер-цикл.
- На самом деле это две части: сначала создается окно. Он принадлежит текущему приложению, поэтому он добавляет себя в Application.Current.Windows. Поскольку это первое показанное окно и Application.Current.MainWindow имеет значение null, оно также устанавливает себя как основное окно. Во-вторых, окно показано модально.
- Так как Application.Current.Windows теперь не является пустым, как только он пуст, завершение работы будет завершено.
- Пользователь закрывает диалоговое окно. Как часть закрытия, окно удаляется из Application.Current.Windows. Кроме того, поскольку это MainWindow, это значение равно null. Так как Application.Current.Windows теперь пуст, запускается shutdown. Однако, поскольку нет цикла диспетчерского цикла, ничего еще не сделано (установлен только внутренний флаг или аналогичный параметр).
- Если вы использовали
app.Run(new DialogWindow()); app.Run(new MainWindow());
, у вас возникло бы исключение при создании MainWindow, так как в этом случае цикл диспетчера работает правильно. Таким образом, он может фактически отключиться, поэтому, когда MainWindow создан, он генерирует исключение, поскольку цикл диспетчера уже отключен.
- Если вы использовали
- Создается MainWindow. Как и выше, он добавляет себя в Application.Current.Windows и устанавливает себя как Application.Current.MainWindow.
- Однако условие завершения приложения уже достигнуто. Но до сих пор приложение не имело шансов что-то сделать.
- Вызывается Run(). Контур диспетчера снова запускается и теперь имеет возможность отключить приложение. Поэтому он закрывает приложение и закрывает все открытые окна.
Итак, нет ошибок.
Таким образом, один из способов решения этой проблемы - изменить OnExplicitShutdown. Затем на шаге 4 нет причин для отключения. Лучше (как в обычном приложении WPF) было бы иметь надлежащее ApplicationDefinition. Удалите StartupUri из App.xaml и вместо этого обработайте событие Startup:
private void OnStartup(object sender, StartupEventArgs e)
{
this.ShutdownMode = ShutdownMode.OnExplicitShutdown;
new DialogWindow().ShowDialog();
var mainWindow = new MainWindow();
this.ShutdownMode = ShutdownMode.OnLastWindowClose; // or OnMainWindowClose
mainWindow.Show();
}
Так как у нас OnExplicitShudown при закрытии диалогового окна, нет никаких оснований для того, чтобы приложение запустилось в этот момент. Затем, после создания MainWindow, мы снова имеем окно как главное окно и как (одно из) окон приложения. Итак, мы можем переключиться в режим выключения, который мы действительно хотим, и показать главное окно.