Why is the Window.Close event propagated?

I came across a strange case when the event of the Close child window extends to the parent window and causes it to close.

I made a minimal example as below

There is nothing for TestWindow except the default WPF window generated by VS

and in App.xaml.cs I override the OnStartup event and use it as a custom user function Main

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

Now, if you press the X button to close TestWindow, the application will shut down and not show MainWindow . If you comment out t.ShowDialog , then MainWindow will display just fine. Then, if you listen to the Closing MainWindow event, you will find that it will fire after TestWindow , which does not seem right to me.

+5
source share
2 answers

In fact, this does not apply; WPF starts your first dialog and closes notifications that there are no additional windows in this process. WPF sends a quit message for later processing. In the meantime, your code has switched to displaying an additional window, which, when processing a message-message, encounters an exit message and closes the window and terminates your application.

Debug Log:

Info: 0: App OnStartup

Info: 0: New MainWindow

Info: 0: Closing MainWindow

Info: 0: application exit

To solve the problem, you need to remove StartupUri and instead handle the Startup event.

Edit:

 <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"> ... 

... in:

 <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"> 

Then drop the code on OnStartup and instead define a handler for 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(); } 

I used to be able to confirm that after closing the dialog box, MainWindow was created; loads and closes quickly.

+4
source

How the App works, it selects the first window started as the main window. Therefore, in your case, TestWindow will be selected as the main window. ShutdownMode in your code is somehow set to OnMainWindowClose . Therefore, after closing TestWindow , all child windows (including your MainWindow ) have Closing .

Thus, the problem here does not extend, but extends to the down closing event.

You should not create a window before your main window starts. Or, if you want, you can set ShutdownMode to OnLastWindowClose .

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

Or you can explicitly set MainWindow in the constructor of the main window:

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

However, if you use ShowDialog() , you cannot explicitly specify MainWindow . Since immediately after closing TestWindow (at that time it is still the main window), the entire application will be disconnected.

Edit : I canโ€™t find a link to this, but it can be checked, and we can be sure of it, here is the debugging:

 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 } 
+3
source

Source: https://habr.com/ru/post/1233387/


All Articles