关闭主窗口时,WPF应用程序不会关闭


82

我习惯于在Visual Studio中进行WinForms编程,但是我想尝试一下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();移到按钮click方法(即上面的按钮)上ShowDialog(),则Visual Studio的行为正确-也就是说,退出应用程序时调试将停止。

为什么会有这种奇怪的行为?

Answers:


137

在您的中MainWindow.xaml.cs,尝试执行以下操作:

protected override void OnClosed(EventArgs e)
{
    base.OnClosed(e);

    Application.Current.Shutdown();
}

通过此链接,您还可以ShutdownMode在XAML中设置:

http://msdn.microsoft.com/zh-CN/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属性值的指定,关闭可以隐式或显式进行。

如果设置ShutdownModeOnLastWindowClose,则Windows Presentation Foundation(WPF)将在应用程序中的最后一个窗口关闭时隐式调用Shutdown,即使将任何当前实例化的窗口设置为主窗口(请参见MainWindow)。

ShutdownModeOnMainWindowClose原因WPF隐式调用shutdown当主窗口关闭,即使其他窗口是当前打开的。

某些应用程序的寿命可能不依赖于主窗口或最后一个窗口何时关闭,或者根本不依赖于窗口。对于这些情况,您需要将ShutdownMode属性设置为OnExplicitShutdown,这需要显式的Shutdown方法调用来停止应用程序。否则,应用程序将继续在后台运行。

ShutdownMode 可以从XAML声明式配置或从代码以编程方式配置。

此属性仅在创建Application对象的线程中可用。


就您而言,该应用无法关闭,因为您可能正在使用默认值OnLastWindowClose

如果设置ShutdownModeOnLastWindowClose,即使应用程序中的最后一个窗口关闭,WPF也会隐式调用Shutdown,即使将任何当前实例化的窗口设置为主窗口(请参阅参考资料MainWindow)。

由于您要打开新窗口而不关闭窗口,因此不会调用shutdown。


1
重要的是要注意,如果您已实例化任何其他线程来执行某些任务,则重写功能最好。关闭之前,请在OnClosed函数中停止线程。否则,线程将保持活动状态,并且该应用程序永远不会真正退出。
weezma2004

35

很高兴您能回答您的问题,但是为了其他人,我也会回答您的问题以添加一些信息。


步骤1

首先,如果要在主窗口关闭时退出程序,则需要指定,因为默认情况下这不是WinForms。

(WPF中的默认值是最后一个窗口关闭时的时间)

在代码中

在入口点转到您的应用程序实例(在VS 2012的WPF程序中,默认值嵌套在App.xaml,因此请其中进入App.xaml.cs并创建一个构造函数)。

在构造函数中,指定您ApplicationShutdownMode应该为ShutdownModeOnLastWindowClose

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

在XAML中

转到您的App.xaml文件VS 2012默认创建(或自行创建)的根是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中

Application像在步骤1中一样转到XAML并指定ApplicationMainWindow您的价值在于Window

MainWindow = "mainWindow";

另类

我不认为这是最好的办法,只是因为WPF不希望你这样做(所以它ApplicationShutdownMode),但你可以只使用一个事件/重写的事件方法(OnEventHappened)。

转到MainWindow的代码隐藏文件并添加:

    protected override void OnClosed(EventArgs e)
    {
        base.OnClosed(e);

        App.Current.Shutdown();
    }

3
您的答案胜于标记的答案。
Seekeer's

我通常以这种方式进行操作:设置MainWindow为主窗口的实例,设置ShutdownModeShutdownMode.OnMainWindowClose,调用事件的MainWindow.Show()回调。这是我想出的最简单的解决方案,至少可以在具有WPF的.NET Core 3中按预期工作。StartupApp
TorbenJ

11

因为WPF应用程序中的默认关闭模式是OnLastWindowClose,这意味着应用程序在最后一个窗口关闭时停止。

当实例化一个新的Window对象时,它会自动添加到应用程序中的Windows列表中。因此,问题在于您的应用程序在启动时正在创建两个窗口-MainWindow和尚未显示的Window01-如果仅关闭MainWindow,则Window01将使您的应用程序保持运行状态。

通常,您将使用与调用其ShowDialog相同的方法创建一个窗口对象,并且每次显示该对话框时都将创建一个新的窗口对象。


2

在寻找其他内容时,我偶然发现了这个问题,但我惊讶地发现没有提及的任何建议答案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. 关闭MainWindow将关闭AdditionalWindow,但关闭AdditionalWindow不会关闭MainWindow
  4. 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();
        }        
    }

1

以上都不适合我,可能是因为我们的项目使用Prism。因此最终在App.XAML.cs中使用了它

    protected override void OnExit(ExitEventArgs e)
    {
        base.OnExit(e);
        Process.GetCurrentProcess().Kill();
    }

0

当我创建第二个窗口作为对话框时,似乎遇到了某些问题。当打开第二个窗口然后将其关闭,然后关闭主窗口时,该应用程序将继续运行(在后台)。我在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();
            }
        }

在调试器中运行时,似乎显示的唯一窗口是我创建为对话框的窗口-换句话说,foreach循环仅找到一个窗口-对话框,而不是主窗口。

我在关闭对话框的方法中运行了“ this.Close()”,并且在“ dlgwin.ShowDialog()”之后添加了一个“ dlgwin.Close()”,但该方法不起作用。甚至没有“ dlgwin = null”。

那么,为什么没有这些多余的东西就不能关闭该对话框?那好吧。这可行。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.