Sunday, September 26, 2010

Hook Into Form’s Events From Controls On Form

Today’s blog post will be another excerpt from my .Net Tips column in the March 2008 Issue of the Universal Thread Magazine.

Following is one methodology one could use to accomplish hooking into Form events from a Control.

Let's use an example to illustrate this ... we'd like our Control to hook into the Form's Load and Closing events. Let's use the ListView as an example. First, we'll sub-class the ListView Control. As you can see we override the OnParentChanged event in the ListView sub-class.

We utilize the TopLevelControl (not the Parent). If the TopLevelControl is null then we hookup event handlers backwards through the control hierarchy as each control is parented. When we finally get to a TopLevelControl for a Form type we hookup the load/close event handlers.
public class MyListView : System.Windows.Forms.ListView
{
private Form _parentForm = null;

public MyListView()
{
}

protected override void OnParentChanged(EventArgs e)
{
base.OnParentChanged(e);

if (this._parentForm != null)
return;

if (this.DesignMode == false)
{
if (this.TopLevelControl != null && this.TopLevelControl is Form)
{
this._parentForm = (Form)this.TopLevelControl;
this.EstablishParentEvents();
}
else
{
Control LastParent = this;

while(LastParent != null)
{
LastParent.ParentChanged += new EventHandler(LastParent_ParentChanged);
LastParent = LastParent.Parent;
}
}
}
}

private void EstablishParentEvents()
{
this._parentForm.Closing += new CancelEventHandler(MyListView_Closing);
this._parentForm.Load += new EventHandler(MyListView_Load);
}

private void MyListView_Closing(object sender, CancelEventArgs e)
{
MessageBox.Show("The parent form is closing!");

if (this._parentForm != null)
{
this._parentForm.Closing -= new CancelEventHandler(MyListView_Closing);
this._parentForm.Load -= new EventHandler(MyListView_Load);
}
}

private void MyListView_Load(object sender, EventArgs e)
{
MessageBox.Show("The parent form is loading!");
}

private void LastParent_ParentChanged(object sender, EventArgs e)
{
Control Source = (Control)sender;

if (Source.TopLevelControl != null && Source.TopLevelControl is Form)
{
this._parentForm = (Form)Source.TopLevelControl;
this.EstablishParentEvents();
}
}
}

Thanks to Neil Tonkin in Message #1084683 on the Universal Thread.