我遇到了一个奇怪的情况,其中子窗口的Close
事件传播到父窗口并导致它也关闭。
我做了一个最小的例子,如下所示
对于TestWindow
,只有VS
并在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
会显示正常。接下来,如果您收听Closing
MainWindow
事件,您会发现它会在TestWindow
关闭后触发,这似乎对我不合适
答案 0 :(得分:4)
它实际上并不是传播,WPF会运行您的第一个对话框,并在关闭时注意到该进程没有其他窗口存在。 WPF发布应用程序退出消息以供稍后处理。与此同时,您的代码已经继续显示另一个窗口,当处理消息时泵会遇到退出消息,因此关闭窗口并终止您的应用程序。
调试日志:
信息:0:App OnStartup
信息:0:新的MainWindow
信息:0:MainWindow关闭
信息:0:应用程序退出
要解决此问题,您需要删除StartupUri
,然后处理Startup
事件。
变化:
<Application x:Class="WpfCloseProblem.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfCloseProblem"
StartupUri="MainWindow.xaml"> ...
...为:
<Application x:Class="WpfCloseProblem.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfCloseProblem"
Startup="Application_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
已创建;快速连续装载和关闭。
答案 1 :(得分:3)
App
的工作方式是选择第一个启动的窗口作为主窗口。因此,在您的情况下,TestWindow
将被选为主窗口。代码中的ShutdownMode
以某种方式设置为OnMainWindowClose
。因此,在关闭TestWindow
后,所有子窗口(包括您的MainWindow
)都会Closing
被解雇。
所以这里的问题不是传播,而是传播 down 结束事件。
在实际首先启动主窗口之前,不应创建任何窗口。或者,如果您愿意,可以将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
}