What event signals that a UserControl is being destroyed?
Solution 1
I suggest the Control::HandleDestroyed event. It is raised, when the underlying HWnd is destroyed (which usually happens, when the parent form is closed). To handle it in your own UserControl, you should override OnHandleDestroyed.
You have full access to the Control's properties at this moment, because it is not yet disposed of.
Solution 2
Another solution
protected override void OnParentChanged(EventArgs e)
{
base.OnParentChanged(e);
if (parentForm != null)
{
parentForm.Closing -= parentForm_Closing;
}
parentForm = FindForm();
if (parentForm != null)
parentForm.Closing += parentForm_Closing;
}
void parentForm_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
parentForm.Closing -= parentForm_Closing;
parentForm = null;
//closing code
}
Solution 3
Why not just use the Disposed
event?
When a form is closing, it will call Dispose
on itself and all child controls will be disposed recursively as well.
Solution 4
Try this:
UserControl.Dispose();
Gary McGill
Updated on September 15, 2020Comments
-
Gary McGill over 3 years
I have a UserControl-derived control the displays some information fetched from a web server. I'm currently in the process of making the initialization of the control asyncronous, to improve responsiveness.
In my Load event handler, I'm creating a CancellationTokenSource, and using the associated Token in the various async calls.
I now want to ensure that if the user closes the form before the async operation completes, the operation will be cancelled. In other words, I want to call Cancel on the token.
I'm trying to figure out where to do this. If there was an Unload event that I could trap, then that would be perfect - but there isn't. In fact, I can't find any event that looks suitable.
I could trap the close event for the containing Form, but I really wanted to keep everything local to my UserControl.
Suggestions?
-
Stephan over 11 yearsAre you sure, the form will call
Dispose
on child controls when closing? I thought it was under the resposibililty of the calling code to dispose of aForm
. -
Gary McGill over 11 yearsHmmm... I'm wary of Dispose, because it's never clear exactly when (and indeed whether) it will be called. If it isn't called until the GC gets involved, then that's too late for my purposes.
-
Gary McGill over 11 yearsI made a similar comment about using the Disposed even (see Mr. Steak's answer). I worry that this event may not be "early" enough, since it may in fact not happen until Dispose is called - since this is an obvious thing for Dispose to do.
-
Gary McGill over 11 yearsI'm more-or-less persuading myself that I need to do it from the point of view of the form itself, rather than keeping it local to the control...
-
Stephan over 11 yearsOk, I found it.
Dispose
is automatically called when closing a modeless form. When displaying a modal dialog by callingForm::ShowDialog()
, the calling code has to do the cleanup (or the garbage collector will do it sooner or later). -
Gary McGill over 11 yearsYeah, that's too many ifs and buts for my liking. I'll change tack, I think. Thanks anyway.
-
Gary McGill over 11 yearsThanks, but I was looking for an event that I could trap that signals to me that the control is being disposed - not for a way to cause it to be disposed.
-
Julien over 10 yearsJust be careful that this is called when the control is used in the designer. One may want to use if (!DesignMode) in the overrides body.
-
yu_sha over 7 yearsThis won't work if control is child of another control - when parent changes the parent form is still null. Solution is to also handle VisibleChanged event.
-
Gabriel Marius Popescu over 7 yearsThe error in the solution above is: An object reference is required for the non-static field, method or property 'Component.Dispose()'
-
Stephan almost 5 years@Elmue: It might be the case that
OnHandleDestroyed
is called somehow byDispose
. But that is not the point.Dispose
of an embedded control is called whenDispose
of the parent is called. When someone does not dispose of a form for some reason thenDispose
on the user control might be called much later. And that does not match the OP's requirements. -
nivs1978 over 2 years@GaryMcGill I think what Gimhan mean is that in the .Designer.cs file you have a dispose method that will be called whenever the parent form the user control is in is closed. In other words you can just ad your code that needs to be run when the UserControl is disposed into this. In case your form is not closed, but the usercontrol is removed from the form, you can call the Dispose() methid directly as Gimhan suggests.