为什么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
将显示正常。 接下来,如果您收听MainWindow
的Closing
事件,您会发现它会在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 }