Monday, November 30, 2009

Hooking Into the Form's Events, from Form Controls

Have you ever had the need to have a Control on your Form hook into some of the Form’s events? For example, say you have a Control on your Form that needs to do something extra when the Form Loads or the Closing event is triggered.

Let's use an example to illustrate how we might accomplish this. 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’ll 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/closing event handlers.

public class MyListView : System.Windows.Forms.ListView
{
private Form FormParent = null;

public MyListView()
{
}

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

if (this.FormParent != null)
return;

if (this.DesignMode == false)
{
if (this.TopLevelControl != null && this.TopLevelControl is Form)
{
this.FormParent = (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.FormParent.Closing += new CancelEventHandler(MyListView_Closing);
this.FormParent.Load += new EventHandler(MyListView_Load);
}

private void MyListView_Closing(object sender, CancelEventArgs e)
{
// put your extra code here

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

private void MyListView_Load(object sender, EventArgs e)
{
// put your extra code here
}

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

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

Thanks to Neil Tonkin in Message #1084683 from the Universal Thread

1 comment:

  1. Hi,
    I am rogsonl, and you helped me with a record that did not seem to be from the datatable it was attached to.
    I could not enter "Thread Title: Table is not updated when one of its records is updated
    Started by: rogsonl" to respond, so I am responding here.
    The problem was caused by creating a binding in the design page of VS, and then reassigning it in the Form.Loading event. When I removed the design definition, the record was the one in the table I controlled.
    I still don't understand how there could have been any data to show on the form, but since the problem was resolved, I am satisfied to leave it there.
    Thank you again for your help
    rogsonl@acm.org

    ReplyDelete