62

I have a WPF window which I am creating from another window by calling Show(), then letting it Close() itself. When the window closes, I expect it to die, call its destructor, and delete all its child elements (such as timers..).

What is the correct way of invoking such an action?

Deantwo
  • 1,113
  • 11
  • 18
vanja.
  • 2,532
  • 3
  • 23
  • 39

5 Answers5

78

Close() releases all unmanaged resources, and closes all owned Windows.

Any other managed resources you need deterministic disposal of should be handled from the Closed event.

Reference

(note: deleted previous answer, it was a completely wrong guess)

mcont
  • 1,749
  • 1
  • 22
  • 33
Simon Buchan
  • 12,707
  • 2
  • 48
  • 55
  • If I click the red cross button on top right corner of a window, will `Close()` be called? – AlpacaMan Jun 29 '22 at 03:07
  • @AlpacaMan, looking at the source, I believe no: calling `Close()` will normally just send the `WM_CLOSE` message to itself, which is also what the native close button does. The message handler then handles that message by doing all the events and cleanup. This is complicated by the edge cases where the native window has gone away or when threading gets involved, but that's the basics. – Simon Buchan Aug 18 '22 at 09:23
16

There are very few WPF elements that actually need to be explicitly disposed, unlike in Windows Forms.

In the case of Window, calling Close() is sufficient to dispose all managed and unmanaged resources accorrding to the documentation.

Samuel Jack
  • 32,712
  • 16
  • 118
  • 155
13

Just in case, I'll add my two cents.

My problem was that I didn't do enough troubleshooting. My window was a child window that could be opened, closed, and re-opened, so I added the following to keep it from closing completely:

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
  e.Cancel = true;
  this.Hide();
}

However, when Window.Close was called, it only hid the window. I eventually caught on and added the following:

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
  e.Cancel = true;
  this.Hide();
}

public void Close() {
  this.Closing -= Window_Closing;
  //Add closing logic here.
  base.Close();
}

This works fine - it removes the event handler preventing the window from being closed, and then closes it.

rookie1024
  • 612
  • 7
  • 18
  • 1
    Hah, I have got the exactly same bug (forgot to unsubscribe close-preventing event handler) when trying to close a child window. Saved my day :) – Nipheris Jan 19 '16 at 14:03
  • This solution is problematic because it hides the original `Window.Close` method. Better to have a separate method to do the same. – Ian Kemp Jan 05 '21 at 13:00
  • @IanKemp I don't advocate for this to be used as a general-purpose solution, but in this case hiding `Window.Close` was perfectly intentional, as calling the hidden method is what resulted in unexpected and incorrect behavior. – rookie1024 Jan 08 '21 at 21:40
1

Closing the window and being confident that you have released all resources to it and any of its children will cause all well behaved elements in the logic tree to be garbage collected.

I say "well behaved" because it's theoretically possible to have an element that does something like create a thread that isn't stopped properly, but in practice if you're using the basic WPF framework and well written controls, you should be fine to just release everything.

Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
0

Regarding resources held by the Window, according to the documentation:

(emphasis added)

Closing a window causes the Closing event to be raised. If the Closing event isn't canceled, the following occurs:

  1. The Window is removed from Application.Windows (if an Application object exists).

  2. The Window is removed from the owner Window if the owner/owned relationship was established before the owned Window was shown and after the owner Window was opened.

  3. The Closed event is raised.

  4. Unmanaged resources created by the Window are disposed.

  5. If ShowDialog was called to show the Window, ShowDialog returns.

I believe this is listed in sequential order.


I'm not sure specifically about the timers sub-question; I don't think the question has enough detail to really answer that.

StayOnTarget
  • 11,743
  • 10
  • 52
  • 81