Introduction
To receive a button click notification, you simply hook up an event handler to your button's Click
event, providing you have a reference to the button. This is very straightforward if the button is directly embedded in the form where the Click
notification needs to be handled. But how do you add an event handler to a button that is embedded in another control, say a UserControl
. Adding a notification handler to that control's Click
event will notify your event handler only if that control was clicked. There is little need to be notified when the mouse is clicked over a UserControl
or Form
.
Event handlers are normally assigned across one level of the control hierarchy, from the Form
directly to a button or from a UserControl
directly to a button. To assign an event handler from a Form
to a button that is embedded in another control is not a straightforward affair. One way to accomplish it would be to expose the button from the UserControl
to the Form
. But this a rather awkward thing to do if the button was nested many layers deep. A much better way is to override the Click
event in the embedding control and redirect the captured Click
event up the food chain. This article describes such a technique. I am using the Button
and its Click
event as a model to demonstrate how to route an event to its final target.
Overriding a Control's event
Let us construct a demo application where two buttons are placed into a user control and the the user control is placed into a form. The button's Click
events are ultimately processed by the form's event handlers. So, the routing needs to be built into the user control. Take a look at the following code snippet:
this.button1.Click += new System.EventHandler(this.button1_Click);
private void button_Click(object sender, System.EventArgs e)
{
base.OnClick(e);
}
private void button_Click(object sender, System.EventArgs e)
{
if(this.EventHandlerDelegate != null)
this.EventHandlerDelegate(sender, e);
}
The EventHandlerDelegate
represents the overridden Click
event of the Button
. The code that overrides it looks like this:
public class UserControl1 : System.Windows.Forms.UserControl
{
public delegate void EventHandler(object sender, System.EventArgs e);
EventHandler EventHandlerDelegate;
new public event EventHandler Click
{
add
{
this.EventHandlerDelegate += value;
}
remove
{
this.EventHandlerDelegate -= value;
}
}
}
Instrumenting the UserControl
in this way permits the Form
to assign its event handlers like so:
this.userControl1.Click += new
EventRouting.UserControl1.EventHandler(this.userControl1_Click);
Event routing also requires some participation by the event consumers to indicate the handling of the event. One other UserControl
implementation demonstrates an event dispatcher that stops dispatching the events as soon as one consumer indicates that the events were handled.
public class EventArgs : System.EventArgs
{
bool handled;
public bool Handled
{
get { return this.handled; }
set { this.handled = value; }
}
}
private void button2_Click(object sender, System.EventArgs e)
{
if(this.EventHandlerDelegate != null)
{
EventArgs e2 = new EventArgs();
object[] args = new object[] { sender, e2 };
foreach(Delegate handler in
this.EventHandlerDelegate.GetInvocationList())
{
handler.DynamicInvoke(args);
if(e2.Handled)
break;
}
}
}
This whole concept is very simple. Just download the code, compile it and observe the show. You can apply this technique for any kind of events including the ones defined by you.