Приложение WPF не закрывается при закрытии главного окна
Я использую для программирования WinForms в Visual Studio, но я хочу попробовать WPF.
Я добавил еще одно окно в мой проект под названием Window01. Главное окно называется MainWindow. Перед конструктором public MainWindow()
объявляю Window01:
Window01 w1;
Теперь я создаю это окно в:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
w1 = new Window01();
}
У меня есть кнопка, где отображается окно: w1.ShowDialog();
.
"Самое смешное" здесь заключается в том, что если я запустим приложение (с отладкой) и выйду его через несколько секунд после (я ничего не делаю в приложении), Visual Studio не останавливает отладку, как будто приложение все еще работает.
Если я перемещаю строку w1 = new Window01();
на метод нажатия кнопки, что означает чуть выше ShowDialog()
, Visual Studio ведет себя правильно - то есть отладка прекращается, когда я выхожу из приложения.
Почему это странное поведение?
Ответы
Ответ 1
В MainWindow.xaml.cs
попробуйте сделать следующее:
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
Application.Current.Shutdown();
}
По этой ссылке вы также можете установить ShutdownMode
в XAML:
http://msdn.microsoft.com/en-us/library/system.windows.application.shutdownmode.aspx
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml"
ShutdownMode="OnExplicitShutdown"
>
</Application>
Приложения останавливаются, только когда вызывается метод Shutdown
Application
. Выключение может выполняться неявно или явно, как указано значением свойства ShutdownMode
.
Если вы установили ShutdownMode
в OnLastWindowClose
, Windows Presentation Foundation (WPF) неявно вызывает Shutdown, когда последнее окно в приложении закрывается, даже если в качестве главного окна задано какое-либо текущее оконное окно (см. MainWindow).
A ShutdownMode
из OnMainWindowClose
заставляет WPF неявно вызывать Shutdown при закрытии MainWindow, даже если в настоящее время открыты другие окна.
Время жизни некоторых приложений может не зависеть от того, закрыто ли главное окно или последнее окно или вообще не зависит от окон. Для этих сценариев вам нужно установить для свойства ShutdownMode
значение OnExplicitShutdown
, для которого требуется явный вызов метода Shutdown
для остановки приложения. В противном случае приложение продолжает работать в фоновом режиме.
ShutdownMode
может быть настроен декларативно из XAML или программно из кода.
Это свойство доступно только из потока, создавшего объект Application
.
В вашем случае приложение не закрывается, потому что вы, вероятно, используете по умолчанию OnLastWindowClose
:
Если вы установите ShutdownMode
на OnLastWindowClose
, WPF неявно вызывает Shutdown, когда последнее окно в приложении закрывается, даже если какие-либо текущие экземпляры Windows устанавливаются в качестве главного окна (см. MainWindow
).
Поскольку вы открываете новое окно и не закрываете его, выключение не вызывает.
Ответ 2
Я рад, что вы получили свой ответ, но ради других я отвечу на ваш вопрос, чтобы добавить некоторую информацию.
Шаг 1
Во-первых, если вы хотите, чтобы ваша программа выходила, когда основное окно закрывается, вам нужно указать, поскольку это не WinForms, где это поведение по умолчанию.
(Значение по умолчанию в WPF при закрытии последнего окна)
В коде
Перейдите к экземпляру вашего приложения в своей точке входа. (В VS $WPF-программе по умолчанию вложен внутри App.xaml
, поэтому перейдите внутри и перейдите к App.xaml.cs
и создайте конструктор).
В конструкторе укажите, что Application
ShutdownMode
должен быть ShutdownMode
. OnLastWindowClose
.
public App()
{
ShutdownMode = ShutdownMode.OnLastWindowClose;
}
В XAML
Перейдите в свой App.xaml
файл, созданный по умолчанию (или создайте его самостоятельно)
Корень - это Application
, укажите внутри Application
ShutdownMode
должен быть ShutdownMode
. OnLastWindowClose
.
<Application x:Class="WpfApplication27.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml"
ShutdownMode="OnMainWindowClose">
Если это сработает, все готово; вы можете прекратить чтение.
Шаг 2
Если вышеуказанное не сработало (я думаю, вы написали приложение WPF с нуля), главное окно, вероятно, не известно приложению в качестве главного окна.
Поэтому укажите это как-хорошо.
В коде
Перейдите к конструктору приложения, как это было на шаге 1, и укажите, что Application
. MainWindow
- это Window
:
MainWindow = mainWindow;
В XAML
Перейдите в Application
XAML, как и на шаге 1, и укажите, что Application
. MainWindow
значение Window
:
MainWindow = "mainWindow";
Alternative
Я не думаю, что это лучший подход, просто потому, что WPF не хочет, чтобы вы это делали (поэтому он Application
ShutdownMode
), но вы можете просто использовать событие/переопределить метод события (OnEventHappened).
Перейдите в файл с кодом ниже, а затем добавьте:
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
App.Current.Shutdown();
}
Ответ 3
Поскольку по умолчанию режим выключения в приложении WPF находится OnLastWindowClose, это означает, что приложение останавливается при закрытии последнего окна.
Когда вы создаете экземпляр нового объекта Window, он автоматически добавляется в список окон в приложении. Таким образом, проблема заключалась в том, что ваше приложение создавало два окна при запуске - MainWindow и еще не показанное Window01 - и если вы только закрыли MainWindow, Window01 будет поддерживать ваше приложение.
Обычно вы создадите объект окна в том же методе, который будет вызывать его ShowDialog, и каждый раз, когда будет показано диалоговое окно, вы создадите новый объект окна.
Ответ 4
Похоже на то, с чем я столкнулся, когда создал второе окно, чтобы действовать как диалоговое окно. Когда второе окно было открыто, а затем закрыто, а затем основное окно было закрыто, приложение продолжало работать (в фоновом режиме). Я добавил (или подтвердил) следующее в своем App.xaml:
<Application x:Class="XXXXXXX.App"
...
StartupUri="MainWindow.xaml"
ShutdownMode="OnMainWindowClose">
<Application.MainWindow >
<NavigationWindow Source="MainWindow.xaml" Visibility="Visible" />
</Application.MainWindow>
Нет радости.
Итак, я, наконец, вошел в свой "MainWindow.xaml" и добавил свойство "Закрыто" в Окно, которое перешло к методу "MainWind_Closed", который выглядит следующим образом:
private void MainWind_Closed(object sender, EventArgs e)
{
foreach ( Window w in App.Current.Windows )
{
if (w.DataContext != this)
w.Close();
}
}
Выполняя отладчик, похоже, что единственное окно, которое отображается, - это окно, которое я создал как диалог, другими словами, цикл foreach находит только одно окно - диалог, а не основной.
У меня было "this.Close()" в методе, который закрыл диалог, и у меня был "dlgwin.Close()", который появился после "dlgwin.ShowDialog()", и это не сработало, Даже "dlgwin = null".
Итак, почему бы не закрыть этот диалог без этого лишнего материала? Ну что ж. Это работает.
Ответ 5
Я наткнулся на этот вопрос, когда искал что-то еще, и я был удивлен тем, что не видел ни одного из предложенных ответов, упоминающих о Window.Owner
.
{
var newWindow = new AdditionalWindow();
newWindow.Owner = Window.GetWindow(this);
// then later on show the window with Show() or ShowDialog()
}
Вызов Window.GetWindow(this)
весьма полезен в представлении приложения MVVM, когда вы находитесь далеко от визуального дерева, не зная, где вы были созданы, его можно вызвать, предоставив любой элемент FrameWork
(например, UserContol
, Button
, Page
). Очевидно, что если у вас есть прямая ссылка на окно, используйте это или даже Application.Current.MainWindow
.
Это довольно мощная связь, которая имеет ряд полезных преимуществ, которые вы, возможно, не понимаете для начала (предполагая, что вы специально не кодировали отдельные окна, чтобы избежать этих отношений).
Если мы будем называть ваше главное окно MainWindow
, а второе - AdditionalWindow
, то....
- Сведение к минимуму
MainWindow
также минимизирует AdditionalWindow
- Восстановление
MainWindow
также восстановит AdditionalWindow
- Закрытие
MainWindow
закрывает AdditionalWindow
, но закрытие AdditionalWindow
не закрывает MainWindow
-
AdditioanlWindow
никогда не будет "потерян" под MainWindow
, т.е. AddditionalWindow
всегда отображается выше MainWindow
в z-порядке, если вы использовали Show()
для его отображения (весьма полезно!)
Следует отметить, что если у вас есть это отношение, событие Closing
на AdditionalWindow
не вызывается, поэтому вам придется вручную перебирать коллекцию OwnedWindows
. например Создайте способ вызова каждого окна с помощью нового интерфейса или метода базового класса.
private void MainWindow_OnClosing(object sender, CancelEventArgs e)
{
foreach (var window in OwnedWindows)
{
var win = window as ICanCancelClosing; // a new interface you have to create
e.Cancel |= win.DoYouWantToCancelClosing();
}
}