closures主窗口时,WPF应用程序不closures
我习惯于Visual Studio中的WinForms编程,但我想给WPF一个尝试。
我为我的项目添加了另一个窗口Window01。 主窗口被称为MainWindow。 在public MainWindow()
构造函数之前,我声明了Window01:
Window01 w1;
现在我实例化这个窗口:
private void Window_Loaded(object sender, RoutedEventArgs e) { w1 = new Window01(); }
我有一个窗口显示的button: w1.ShowDialog();
。
这里的“有趣的”事情是,如果我启动应用程序(debugging)并在几秒钟后退出(我没有在应用程序中做任何事情),Visual Studio不会停止debugging,就好像应用程序是仍在运行。
如果我移动w1 = new Window01();
对于button点击方法,意思就是在ShowDialog()
之上,Visual Studio运行正常 – 也就是说,当我退出应用程序时,debugging停止。
为什么这个奇怪的行为
在你的MainWindow.xaml.cs
,尝试这样做:
protected override void OnClosed(EventArgs e) { base.OnClosed(e); Application.Current.Shutdown(); }
通过此链接,还可以在XAML中设置ShutdownMode
:
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>
应用程序只有在调用Application
的Shutdown
方法时才会停止运行。 closures可以隐式或显式执行,如ShutdownMode
属性的值所指定。
如果将ShutdownMode
设置为OnLastWindowClose
,即使任何当前实例化的窗口设置为主窗口(请参阅MainWindow),Windows Presentation Foundation(WPF)也会在应用程序的最后一个窗口closures时隐式调用Shutdown。
当MainWindowclosures时, OnMainWindowClose
的ShutdownMode
会导致WPF隐式调用Shutdown,即使其他窗口当前处于打开状态。
某些应用程序的生命周期可能不依赖于主窗口或最后一个窗口何时closures,或者根本不依赖于窗口。 对于这些场景,您需要将ShutdownMode
属性设置为OnExplicitShutdown
,这需要显式的Shutdown
方法调用来停止应用程序。 否则,应用程序将继续在后台运行。
ShutdownMode
可以从XAML声明式configuration,也可以通过编程从代码中configuration。
该属性仅可用于创buildApplication
对象的线程。
在你的情况下,应用程序不closures,因为你可能使用默认的OnLastWindowClose
:
如果将ShutdownMode
设置为OnLastWindowClose
,即使任何当前实例化的窗口设置为主窗口(请参阅MainWindow
),WPF OnLastWindowClose
在应用程序的最后一个窗口closures时隐式调用Shutdown。
由于您打开一个新窗口,而不是closures它,关机不会被调用。
我很高兴你得到了你的答案,但为了别人的缘故,我会回答你的问题 – 好添加一些信息。
步骤1
首先,如果你希望你的程序在主窗口closures的时候退出,你需要指定,因为这不是默认情况下的WinForms。
(WPF中的默认值是最后一个窗口closures的时候)
在代码中
进入你的应用程序实例(在VS 2012的WPF程序中,默认嵌套在App.xaml
,所以进入它并导航到App.xaml.cs
并创build一个构造函数)。
在构造函数中指定Application
的ShutdownMode
应该是ShutdownMode
。 OnLastWindowClose
。
public App() { ShutdownMode = ShutdownMode.OnLastWindowClose; }
在XAML中
转到VS 2012默认创build的App.xaml
文件(或者自己创build)。根是一个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中
像步骤1中那样转到Application
XAML,并指定该Application
。 MainWindow
的值是你的Window
:
MainWindow = "mainWindow";
替代
我不认为这是最好的办法,只是因为WPF不希望你这样做(所以它有Application
的ShutdownMode
),但你可以使用事件/重写事件方法(OnEventHappened)。
转到MainWindow的代码隐藏文件并添加:
protected override void OnClosed(EventArgs e) { base.OnClosed(e); App.Current.Shutdown(); }
因为WPF应用程序中的默认closures模式是OnLastWindowClose,这意味着应用程序在最后一个窗口closures时停止。
当您实例化一个新的Window对象时,它会自动添加到应用程序中的窗口列表中 。 所以,问题是你的应用程序在开始时创build了两个窗口 – MainWindow和还没有显示的Window01 – 如果你只closures了MainWindow,那么Window01会让你的应用程序保持运行。
通常,您将使用与调用其ShowDialog的方法相同的方法创build一个窗口对象,并且每次显示对话框时都将创build一个新的窗口对象。
它看起来像我创build第二个窗口作为一个对话框时遇到的东西。 当第二个窗口打开,然后closures,然后closures主窗口,应用程序继续运行(在后台)。 我在我的App.xaml中添加(或确认)了以下内容:
<Application x:Class="XXXXXXX.App" ... StartupUri="MainWindow.xaml" ShutdownMode="OnMainWindowClose"> <Application.MainWindow > <NavigationWindow Source="MainWindow.xaml" Visibility="Visible" /> </Application.MainWindow>
没有快乐。
所以,我终于进入了我的“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(); } }
通过debugging程序运行,它看起来像是我创build的窗口是唯一的窗口 – 换句话说,foreach循环只能find一个窗口 – 对话框,而不是主窗口。
我已经在closures对话框的方法中运行了“this.Close()”,并且在“dlgwin.ShowDialog()”后面有一个“dlgwin.Close()”,但这并不起作用。 甚至没有“dlgwin = null”。
那么,如果没有这些额外的东西,为什么不能closures对话? 好吧。 这工作。
当我search别的东西的时候,我偶然发现了这个问题,我很惊讶我看不到任何关于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
- closures
MainWindow
将closuresAdditionalWindow
,但closuresAdditionalWindow
将不closuresMainWindow
-
AdditioanlWindow
永远不会在MainWindow
下面“失去”,即如果你使用Show()
来显示它,那么AddditionalWindow
总是以z顺序显示在MainWindow
之上(非常有用!)
有一点需要注意,如果你有这个关系,那么AdditionalWindow
上的Closing
事件不会被调用,所以你必须手动迭代OwnedWindows
集合。 例如创build一个方法来通过一个新的接口或基类方法来调用每个窗口。
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(); } }