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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9992119/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 12:02:15  来源:igfitidea点击:

WPF App Doesn't Shut Down When Closing Main Window

c#wpfvisual-studio-2010window

提问by eightx2

I'm used to WinForms programming in Visual Studio, but I wanted to give WPF a try.

我习惯于在 Visual Studio 中进行 WinForms 编程,但我想尝试一下 WPF。

I added another window to my project, called Window01. The main window is called MainWindow. Before the public MainWindow()constructor I declare Window01:

我在我的项目中添加了另一个窗口,称为 Window01。主窗口称为 MainWindow。在public MainWindow()构造函数之前,我声明 Window01:

Window01 w1;

Now I instantiate this window in:

现在我实例化这个窗口:

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    w1 = new Window01();            
}

I have a button where the window is shown: w1.ShowDialog();.

我有一个显示窗口的按钮:w1.ShowDialog();

The 'funny' thing here is the fact that if I start the application (with debugging) and exit it a few seconds after (I don't do anything in the application), Visual Studio doesn't stop debugging as if the application is still running.

这里“有趣”的事情是,如果我启动应用程序(带调试)并在几秒钟后退出(我不在应用程序中执行任何操作),Visual Studio 不会停止调试,就好像应用程序是仍在运行。

If I move the line w1 = new Window01();to the button click method, meaning just above ShowDialog(), Visual Studio is behaving properly - that is, the debugging stops when I exit the application.

如果我将行移动w1 = new Window01();到按钮单击方法,意思是就在上面ShowDialog(),Visual Studio 运行正常 - 也就是说,当我退出应用程序时调试停止。

Why this strange behaviour?

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

采纳答案by Bob Horn

In your MainWindow.xaml.cs, try doing this:

在您的 中MainWindow.xaml.cs,尝试这样做:

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

    Application.Current.Shutdown();
}

Per this link, you can also set the ShutdownModein XAML:

根据此链接,您还可以ShutdownMode在 XAML 中设置:

http://msdn.microsoft.com/en-us/library/system.windows.application.shutdownmode.aspx

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>

Applications stop running only when the Shutdownmethod of the Applicationis called. Shut down can occur implicitly or explicitly, as specified by the value of the ShutdownModeproperty.

应用程序仅在调用的Shutdown方法时停止运行Application。关闭可以隐式或显式发生,由ShutdownMode属性值指定。

If you set ShutdownModeto OnLastWindowClose, Windows Presentation Foundation (WPF) implicitly calls Shutdown when the last window in an application closes, even if any currently instantiated windows are set as the main window (see MainWindow).

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

A ShutdownModeof OnMainWindowClosecauses WPF to implicitly call Shutdown when the MainWindow closes, even if other windows are currently open.

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

The lifetime of some applications may not be dependent on when the main window or last window is closed, or may not be dependent on windows at all. For these scenarios you need to set the ShutdownModeproperty to OnExplicitShutdown, which requires an explicit Shutdownmethod call to stop the application. Otherwise, the application continues running in the background.

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

ShutdownModecan be configured declaratively from XAML or programmatically from code.

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

This property is available only from the thread that created the Applicationobject.

此属性仅可从创建Application对象的线程使用。



In your case, the app isn't closing because you're probably using the default OnLastWindowClose:

在您的情况下,应用程序没有关闭,因为您可能使用的是默认值OnLastWindowClose

If you set ShutdownModeto OnLastWindowClose, WPF implicitly calls Shutdown when the last window in an application closes, even if any currently instantiated windows are set as the main window (see MainWindow).

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

Since you're opening a new window, and not closing it, shutdown doesn't get called.

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

回答by Joe Daley

Because the default shutdown modein a WPF application is OnLastWindowClose, which means the application stops when the last window closes.

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

When you instantiate a new Window object, it automatically gets added to the list of windowsin the application. So, the problem was that your application was creating two windows when it started - the MainWindow and the not-yet-shown Window01 - and if you only closed the MainWindow, the Window01 would keep your application running.

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

Normally, you will create a window object in the same method that is going to call its ShowDialog, and you will create a new window object each time the dialog is shown.

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

回答by MasterMastic

I'm glad you got your answer but for the sake of others I'll answer your question as-well to add some information.

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



Step 1

第1步

First, if you want your program to exit when the main window closes down, you need to specify, since this is not WinForms where this behavior is default.

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

(The default in WPF is when the last window closes down)

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

In Code

在代码中

Go to your application instance in your entry point (In VS 2012's WPF program the default is nested inside App.xaml, so go insideit and navigate to App.xaml.cs& create a constructor).

在您的入口点转到您的应用程序实例(在VS 2012的WPF程序默认是嵌套的内部App.xaml,所以去里面它并导航到App.xaml.cs与创建一个构造函数)。

In the constructor specify that your Application's ShutdownModeshould be ShutdownMode.OnLastWindowClose.

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

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

In XAML

在 XAML 中

Go to your App.xamlfile that VS 2012 created by default (or create it yourself) The root is an Application, specify inside that your Application's ShutdownModeshould be ShutdownMode.OnLastWindowClose.

转到App.xamlVS 2012 默认创建的文件(或自己创建)根是Application,在里面指定你ApplicationShutdownMode应该是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">

If it works, you're done; you can stop reading.

如果它有效,你就完成了;你可以停止阅读。



Step 2

第2步

If the above didn't work (I guess you wrote the WPF application from scratch), the main window probably isn't known to the application as the main window. So specify that as-well.

如果上述方法不起作用(我猜您是从头开始编写 WPF 应用程序的),则应用程序可能不知道主窗口是主窗口。所以也指定。

In Code

在代码中

Go to the application's constructor as you did in Step 1, and specify that Application.MainWindow's value is your Window:

像在步骤 1 中一样转到应用程序的构造函数,并指定Application. MainWindow的价值是你的Window

MainWindow = mainWindow;

In XAML

在 XAML 中

Go to the ApplicationXAML as you did in Step 1, and specify that Application.MainWindow's value is your Window:

Application像在步骤 1 中一样转到XAML,并指定Application. MainWindow的价值是你的Window

MainWindow = "mainWindow";


Alternative

选择

I don't think this is the best approach, just because WPF doesn't want you to do this (so it has Application's ShutdownMode), but you can just use an event / override an event method (OnEventHappened).

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

Go to the MainWindow's code-behind file and add:

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

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

        App.Current.Shutdown();
    }

回答by Lowell

It looks like something I ran into when I created a second window to act as a dialog box. When the second window was opened and then closed and then the main window was closed, the app kept running (in the background). I added (or confirmed) the following in my App.xaml:

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

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

No joy.

没有喜悦。

So, I finally went into my "MainWindow.xaml" and added a "Closed" property to the Window which went to a "MainWind_Closed" method that looks like the following:

所以,我终于进入了我的“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();
            }
        }

Running through the debugger, it looks like the only window that shows up is the window I created as a dialog--in other words, the foreach loop only finds one window--the dialog, not the main.

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

I had "this.Close()" running in the method that closed the dialog, and I had a "dlgwin.Close()" that came after the "dlgwin.ShowDialog()", and that didn't work. Not even a "dlgwin = null".

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

So, why wouldn't that dialog close without this extra stuff? Oh well. This works.

那么,如果没有这些额外的东西,为什么那个对话框不会关闭呢?那好吧。这有效。

回答by Rhys

I stumbled across this Question when searching for something else and I was surprised that I could not see any of the proposed answers mentioning about Window.Owner.

我在搜索其他内容时偶然发现了这个问题,我很惊讶我看不到任何提到的建议答案Window.Owner

    {
       var newWindow = new AdditionalWindow();
       newWindow.Owner = Window.GetWindow(this);

       // then later on show the window with Show() or ShowDialog()
    }

A call to Window.GetWindow(this)is quite useful in View of an MVVM application when you are far down the visual tree not knowing where you have been instantiated, it can be called by supplying any FrameWorkelement (e.g. UserContol, Button, Page). Obviously if you have a direct reference to the window then use that or even Application.Current.MainWindow.

Window.GetWindow(this)在 MVVM 应用程序的视图中,当您在可视化树的下方不知道您已实例化的位置时,调用是非常有用的,它可以通过提供任何FrameWork元素(例如UserContolButtonPage)来调用。显然,如果您有对窗口的直接引用,则使用那个甚至Application.Current.MainWindow.

This is quite a powerful relationship that has a number of useful benefits that you might not realise to begin with (assuming you have not specifically coded separate windows to avoided these relationships).

这是一个非常强大的关系,它具有许多您可能没有意识到的有用好处(假设您没有专门编写单独的窗口来避免这些关系)。

If we call your main window MainWindowand the second window as AdditionalWindowthen....

如果我们将您的主窗口MainWindow和第二个窗口称为AdditionalWindow那么....

  1. Minimising the MainWindowwill also minimise AdditionalWindow
  2. Restoring MainWindowwill also restore AdditionalWindow
  3. Closing MainWindowwill close AdditionalWindow, but closing AdditionalWindowwill not close MainWindow
  4. AdditioanlWindowwill never get "lost" under MainWindow, i.e. AddditionalWindowalways shows above MainWindowin the z-order if you used Show()to display it (quite useful!)
  1. 最小化MainWindow也将最小化AdditionalWindow
  2. 恢复MainWindow也会恢复AdditionalWindow
  3. 关闭MainWindow会关闭AdditionalWindow,但关闭AdditionalWindow不会关闭MainWindow
  4. AdditioanlWindow永远不会在 下“丢失” MainWindow,即如果您曾经显示它,则AddditionalWindow始终MainWindow以 z 顺序显示在上方Show()(非常有用!)

One thing to note though, if you have this relationship, then the Closingevent on the AdditionalWindowis not called, so you'd have to manually iterate over the OwnedWindowscollection. e.g. Create a way to call each window via a new Interface, or base class method.

但是需要注意的一件事是,如果您有这种关系,则不会调用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();
        }        
    }

回答by sadis

None of the above worked for me, maybe because our project uses Prism. So ended up using this in the App.XAML.cs

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

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