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

时间:2012-04-03 11:14:26

标签: c# wpf visual-studio-2010 window

我已经习惯了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();移动到按钮单击方法,即ShowDialog()上方,Visual Studio的行为正常 - 也就是说,当我退出应用程序时调试停止。

为什么会出现这种奇怪的行为?

6 个答案:

答案 0 :(得分:115)

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>

只有在调用Shutdown的{​​{1}}方法时,应用程序才会停止运行。关闭可以隐式或显式发生,由Application属性的值指定。

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

OnLastWindowClose ShutdownMode会导致WPF在MainWindow关闭时隐式调用Shutdown,即使其他窗口当前处于打开状态。

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

Shutdown可以从XAML以声明方式配置,也可以从代码以编程方式配置。

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


在您的情况下,应用未关闭,因为您可能使用默认的Application

如果将OnLastWindowClose设置为ShutdownMode,则当应用程序中的最后一个窗口关闭时,WPF会隐式调用Shutdown,即使当前实例化的任何窗口都设置为主窗口(请参阅OnLastWindowClose )。

由于您正在打开一个新窗口,而不是关闭它,因此不会调用shutdown。

答案 1 :(得分:25)

我很高兴你得到了答案,但为了别人的缘故,我会回答你的问题,以便添加一些信息。


第1步

首先,如果您希望程序在主窗口关闭时退出,则需要指定,因为这不是WinForms,此行为是默认行为。

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

代码

转到您的入口点的应用程序实例(在VS 2012的WPF程序中,默认设置嵌套在App.xaml内,所以在里面,然后导航到App.xaml.cs&amp;创建一个构造函数)。

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

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

在XAML中

转到默认情况下创建的VS 2012的App.xaml文件(或自行创建) 根目录是Application,在ApplicationShutdownMode ShutdownMode ApplicationOnLastWindowClose指定内部。

<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中一样,并指定MainWindowWindow的值是您的Application

MainWindow = mainWindow;

在XAML中

转到步骤1中的Application XAML,并指定MainWindowWindow的值为Application

MainWindow = "mainWindow";

替代

我不认为这是最好的方法,因为WPF不希望你这样做(所以它有ShutdownMode的{{3}}),但你可以只使用一个事件/覆盖事件方法(OnEventHappened)。

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

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

        App.Current.Shutdown();
    }

答案 2 :(得分:11)

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

当您实例化一个新的Window对象时,它会自动添加到应用程序中的list of windows。所以,问题是你的应用程序在启动时创建了两个窗口 - MainWindow和尚未显示的Window01 - 如果你只关闭了MainWindow,Window01会让你的应用程序保持运行。

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

答案 3 :(得分:0)

当我创建第二个窗口作为对话框时,它看起来像我遇到的东西。当第二个窗口打开然后关闭然后主窗口关闭时,应用程序继续运行(在后台)。我在App.xaml中添加(或确认)以下内容:

<Application x:Class="XXXXXXX.App"
             ...  
             StartupUri="MainWindow.xaml"
             ShutdownMode="OnMainWindowClose">
    <Application.MainWindow >
        <NavigationWindow Source="MainWindow.xaml" Visibility="Visible" />
    </Application.MainWindow>

没有快乐。

所以,我终于进入了我的&#34; MainWindow.xaml&#34;并添加了一个&#34;已关闭&#34;窗口的属性转到&#34; MainWind_Closed&#34;方法如下所示:

 private void MainWind_Closed(object sender, EventArgs e)
        {
            foreach ( Window w in App.Current.Windows )
            {
                if (w.DataContext != this)
                    w.Close();
            }
        }

通过调试器运行,看起来唯一显示的窗口是我创建的窗口作为对话框 - 换句话说,foreach循环只找到一个窗口 - 对话框,而不是主窗口。

我有&#34; this.Close()&#34;在关闭对话框的方法中运行,我有一个&#34; dlgwin.Close()&#34;在&#34; dlgwin.ShowDialog()&#34;之后出现,但是没有用。甚至不是&#34; dlgwin = null&#34;。

那么,为什么在没有这些额外的东西的情况下,该对话关闭呢?那好吧。这很有效。

答案 4 :(得分:0)

我在搜索其他内容时偶然发现了这个问题,我很惊讶我看不到任何提及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永远不会失去&#34;在MainWindow下,如果您使用AddditionalWindow来展示它,那么MainWindow始终会在z序中显示Show()以上(非常有用!)
  5. 有一点需要注意,如果你有这种关系,那么Closing上的AdditionalWindow事件就不会被调用,所以你必须手动迭代{{1}收集。例如创建一种通过新接口或基类方法调用每个窗口的方法。

    OwnedWindows

答案 5 :(得分:0)

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

中使用了它
    protected override void OnExit(ExitEventArgs e)
    {
        base.OnExit(e);
        Process.GetCurrentProcess().Kill();
    }