2

I had issue today and while trying to solve it found something strange in WPF.

To see problem, create new WPF application, add button and click event:

private void Button_Click(object sender, RoutedEventArgs e)
{
    var window = new MainWindow();
}

Starting application and closing it without clicking button will work.

Starting application, clicking button and closing it - will not work.

Application will stay in memory. Some months ago I had similar issue, but if I use solution from it, then another weird thing occurs: when exiting application, Window.Closed event is fired for a never displayed window.

Questions: What does WPF do when instantiating window? Why I can't simply instantiate it like any other class? Must I always display it?

Community
  • 1
  • 1
Sinatr
  • 20,892
  • 15
  • 90
  • 319
  • I'm sorry, I misunderstood what you were trying to accomplish. Are you trying to create a window and then auto-destroy it when closing the main/outer window? – rae1 Jun 06 '14 at 13:46
  • @rae1, sort of. I don't care what happens with window, I simply need its instance (which will load xaml, init everything, etc) so I can use that. But I don't want to display window at all. – Sinatr Jun 06 '14 at 13:50

1 Answers1

1

I believe you are looking at this from the wrong perspective. You should not need to create a window this way if you are not going to display it.

The issue you are facing is due to the window you created on the click event never being disposed (which happens when you call Close), and so the UI loop continues to execute and the application never exits.

You can avoid this by also calling Close when you close the outer/visible window, as such,

    private Window window;

    public MainWindow()
    {
        InitializeComponent();
    }

    public void ButtonBase_OnClick(object sender, RoutedEventArgs e)
    {
        window = new MainWindow();
    }

    protected override void OnClosed(EventArgs e)
    {
        if (window != null)
        {
            // Call Close on the window you created when the main main closes
            window.Close(); 
        }

        base.OnClosed(e);
    }

You need to use a private field so you can keep a reference when the OnClosed event is called.

I've tested this with a simple WPF application; however, you should not be instantiating the same window type (i.e. MainWindow) on the click event. I did this for simplicity, but it is utterly unnecessary.

rae1
  • 6,066
  • 4
  • 27
  • 48
  • This works. Now I have to think how to adapt it to my [*multiple window* solution](http://stackoverflow.com/a/22605376/1997232), because calling `Close` there for just a local instance of window will close whole application. I think there was some property for `app.xaml`. – Sinatr Jun 06 '14 at 14:07
  • Again, you might have to rethink your architecture because this is for all effects a hack, and should *not* be implemented application wide. Either way, happy to help. =) – rae1 Jun 06 '14 at 14:09
  • I have to use `hack` it seems. I could add bounty to old question and see if someone can offer a better architecture. And yes, closing window before leaving event does all the magic. Only missing thing was `ShutdownMode="OnExplicitShutdown"` in `App.xaml`. – Sinatr Jun 06 '14 at 14:21