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> 

应用程序只有在调用ApplicationShutdown方法时才会停止运行。 closures可以隐式或显式执行,如ShutdownMode属性的值所指定。

如果将ShutdownMode设置为OnLastWindowClose ,即使任何当前实例化的窗口设置为主窗口(请参阅MainWindow),Windows Presentation Foundation(WPF)也会在应用程序的最后一个窗口closures时隐式调用Shutdown。

当MainWindowclosures时, OnMainWindowCloseShutdownMode会导致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一个构造函数)。

在构造函数中指定ApplicationShutdownMode应该是ShutdownModeOnLastWindowClose

  public App() { ShutdownMode = ShutdownMode.OnLastWindowClose; } 

在XAML中

转到VS 2012默认创build的App.xaml文件(或者自己创build)。根是一个Application ,在里面指定你的ApplicationShutdownMode应该是ShutdownModeOnLastWindowClose

 <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中一样转到应用程序的构造函数,然后指定该ApplicationMainWindow的值是你的Window

 MainWindow = mainWindow; 

在XAML中

像步骤1中那样转到Application XAML,并指定该ApplicationMainWindow的值是你的Window

 MainWindow = "mainWindow"; 

替代

我不认为这是最好的办法,只是因为WPF不希望你这样做(所以它有ApplicationShutdownMode ),但你可以使用事件/重写事件方法(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元素来调用它(例如UserContolButtonPage )。 显然,如果你有一个直接的引用窗口,那么使用,甚至Application.Current.MainWindow

这是一个非常强大的关系,有许多有用的好处,你可能没有意识到开始(假设你没有专门编码单独的窗口,以避免这些关系)。

如果我们调用你的主窗口MainWindow ,第二个窗口为AdditionalWindow那么….

  1. 最小化MainWindow也将最小化AdditionalWindow
  2. 恢复MainWindow也会恢复AdditionalWindow
  3. closuresMainWindow将closuresAdditionalWindow ,但closuresAdditionalWindow将不closuresMainWindow
  4. 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(); } }