Приложение 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 ведет себя правильно - то есть отладка останавливается при выходе из приложения.
почему такое странное поведение?
5 ответов
в своем 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) неявно вызывает завершение работы, когда последнее окно в приложении закрывается, даже если в качестве главного окна заданы какие-либо текущие экземпляры windows (см. MainWindow).
A ShutdownMode
of OnMainWindowClose
заставляет WPF неявно вызывать завершение работы при закрытии главного окна, даже если другие окна в настоящее время открыты.
срок службы некоторых приложений может не зависеть от того, когда закрыто главное или последнее окно, или не может будьте зависимы от windows вообще. Для этих сценариев необходимо установить ShutdownMode
свойство OnExplicitShutdown
, что требует явного Shutdown
вызов метода для остановки приложения. В противном случае приложение продолжает работать в фоновом режиме.
ShutdownMode
можно настроить декларативно из XAML или программно из кода.
это свойство доступно только из потока, который создал
я рад, что вы получили свой ответ, но ради других я отвечу на ваш вопрос, а также, чтобы добавить некоторую информацию.
Шаг 1
во-первых, если вы хотите, чтобы ваша программа вышла, когда главное окно закрывается, вам нужно указать, так как это не WinForms, где это поведение по умолчанию.
(по умолчанию в WPF, когда последнее окно закрывается)
Код
перейти к экземпляр приложения в точке входа (в программе WPF VS 2012 по умолчанию вложен внутри App.xaml
, так что иди внутри и выберите App.xaml.cs
& создать конструктор).
в конструкторе укажите, что ваш Application
' s ShutdownMode
должно быть ShutdownMode
.OnLastWindowClose
.
public App()
{
ShutdownMode = ShutdownMode.OnLastWindowClose;
}
в XAML
перейти к вашей App.xaml
файл, созданный по умолчанию VS 2012 (или создать это сами)
Корень -Application
, указать, что внутри вашего Application
' s 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
's значение является вашим Window
:
MainWindow = "mainWindow";
альтернатива
я не думаю, что это лучший подход, просто потому, что WPF не хочет, чтобы вы это делали (так что у него есть Application
' s ShutdownMode
), но вы можете просто использовать событие / переопределить метод события (OnEventHappened).
"перейти к коду" -за файл MainWindow файл и добавить:
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
App.Current.Shutdown();
}
потому что по умолчанию режим отключения в приложении WPF является OnLastWindowClose, что означает, что приложение останавливается при закрытии последнего окна.
при создании экземпляра нового объекта Window он автоматически добавляется в список Windows в приложение. Таким образом, проблема заключалась в том, что ваше приложение создавало два окна при запуске - главное окно и еще не показанное Window01-и если вы только закрыли главное окно, Window01 будет держать ваше приложение работает.
обычно вы создадите объект window тем же методом, который будет вызывать его ShowDialog, и вы будете создавать новый объект window каждый раз, когда отображается диалоговое окно.
это похоже на то, с чем я столкнулся, когда создал второе окно, чтобы действовать как диалоговое окно. Когда второе окно было открыто, а затем закрыто, а затем Главное окно было закрыто, приложение продолжало работать (в фоновом режиме). Я добавил (Или подтвердил) следующее В своем приложении.язык XAML:
<Application x:Class="XXXXXXX.App"
...
StartupUri="MainWindow.xaml"
ShutdownMode="OnMainWindowClose">
<Application.MainWindow >
<NavigationWindow Source="MainWindow.xaml" Visibility="Visible" />
</Application.MainWindow>
никакой радости.
Итак, я, наконец, вошел в свое "главное окно".xaml "и добавил свойство" Closed " в окно, которое перешло к методу "MainWind_Closed", который выглядит как следующий:
private void MainWind_Closed(object sender, EventArgs e)
{
foreach ( Window w in App.Current.Windows )
{
if (w.DataContext != this)
w.Close();
}
}
запуск через отладчик, похоже, единственное окно, которое появляется, - это окно, которое я создал как диалог,другими словами, цикл foreach находит только одно окно-диалог, а не основной.
у меня было "это.Close () "работает в методе, который закрыл диалоговое окно, и у меня был" dlgwin.Close ()", который пришел после " dlgwin.ShowDialog ()", и это не сработало. Даже не "dlgwin = null".
Итак, почему бы этому диалогу не закрыться без эти лишние вещи? Ну что ж. Эта работа.
я наткнулся на этот вопрос при поиске чего-то еще, и я был удивлен, что не видел ни одного из предложенных ответов, упоминающих о 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();
}
}