为什么Window.Close事件会传播?

我遇到了一个奇怪的情况,子窗口的Close事件传播到父窗口并导致它关闭。

我做了一个最小的例子,如下所示

对于TestWindow ,只有VS生成的默认WPF窗口

App.xaml.cs我重写OnStartup事件并将其用作自定义Main函数

 protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); TestWindow t = new TestWindow(); t.ShowDialog(); } 

现在,如果单击X按钮关闭TestWindow,应用程序将关闭而不是显示MainWindow 。 如果您注释掉t.ShowDialog那么MainWindow将显示正常。 接下来,如果您收听MainWindowClosing事件,您会发现它会在TestWindow关闭后触发,这对我来说似乎不对

它实际上并没有传播 ,WPF运行你的第一个对话框,并在关闭通知时,该进程没有进一步的窗口。 WPF发布应用程序退出消息以供以后处理。 与此同时,您的代码已经继续显示另一个窗口,当处理消息泵时遇到退出消息,因此关闭窗口并终止您的应用程序。

调试日志:

信息:0:App OnStartup

信息:0:新的MainWindow

信息:0:MainWindow关闭

信息:0:App退出

要解决此问题,您需要删除StartupUri ,而是处理Startup事件。

更改:

  ... 

…至:

  

然后丢弃OnStartup上的代码,而是为Startup定义一个处理程序:

 //protected override void OnStartup(StartupEventArgs e) //{ // base.OnStartup(e); // // TestWindow t = new TestWindow(); // t.ShowDialog(); //} private void Application_Startup(object sender, StartupEventArgs e) { var main = new MainWindow(); TestWindow t = new TestWindow(); t.ShowDialog(); main.Show(); } 

以前我能够确认对话关闭后, MainWindow被创建了; 快速连续装载和关闭。

App在这里工作的方式是选择第一个启动的窗口作为主窗口。 因此,在您的情况下, TestWindow将被选为主窗口。 代码中的ShutdownMode以某种方式设置为OnMainWindowClose 。 因此,在关闭TestWindow ,所有子窗口(包括您的MainWindow )都会触发Closing

所以这里的问题不是传播,而是在结束事件中传播。

在实际首先启动主窗口之前,不应创建任何窗口。 或者,如果需要,可以将ShutdownMode设置为OnLastWindowClose

 protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); Application.Current.ShutdownMode = ShutdownMode.OnLastWindowClose; TestWindow t = new TestWindow(); t.ShowDialog(); } 

或者,您可以在主窗口的构造函数中显式设置MainWindow

 public MainWindow(){ InitializeComponent(); Application.Current.MainWindow = this; } 

但是,如果使用ShowDialog() ,则无法显式设置MainWindow 。 因为在关闭TestWindow (当时它仍然是主窗口),整个应用程序将被关闭。

编辑 :我没有找到任何关于此的参考,但它可以检查,我们可以确定,这是调试:

 protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); new TestWindow();//not even need to be shown var wm = Application.Current.MainWindow;// points to the new TestWindow //If there is not any Window init here, the MainWindow is just null }