Tuesday, September 06, 2005

Event Bubbling From Web User Controls in ASP.NET (C#)

This C# code example demonstrates event bubbling from a web user control (ASCX) to a parent page (ASPX) and the shows the flow of events through execution.
Some user controls are entirely self contained, for example, a user control displaying current stock quotes does not need to interact with any other content on the page. Other user controls will contain buttons to post back. Although it is possible to subscribe to the button click event from the containing page, doing so would break some of the object oriented rules of encapsulation. A better idea is to publish an event in the user control to allow any interested parties to handle the event.

This technique is commonly referred to as “event bubbling” since the event can continue to pass through layers, starting at the bottom (the user control) and perhaps reaching the top level (the page) like a bubble moving up a champagne glass.

For starters, let’s create a user control with a button attached.

WebUserControl1

The code behind for the user control looks like the following.

public class WebUserControl1 : System.Web.UI.UserControl
{
protected System.Web.UI.WebControls.Button Button1;
protected System.Web.UI.WebControls.Panel Panel1;

private void Page_Load(object sender, System.EventArgs e)
{
Response.Write("WebUserControl1 :: Page_Load
");
}

private void Button1_Click(object sender, System.EventArgs e)
{
Response.Write("WebUserControl1 :: Begin Button1_Click
");
OnBubbleClick(e);
Response.Write("WebUserControl1 :: End Button1_Click
");
}

public event EventHandler BubbleClick;

protected void OnBubbleClick(EventArgs e)
{
if(BubbleClick != null)
{
BubbleClick(this, e);
}
}

#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
InitializeComponent();
base.OnInit(e);
}

private void InitializeComponent()
{
this.Button1.Click += new System.EventHandler(this.Button1_Click);
this.Load += new System.EventHandler(this.Page_Load);

}
#endregion

}


The user control specifies a public event (BubbleClick) which declares a delegate. Anyone interested in the BubbleClick event can add an EventHandler method to execute when the event fires – just like the user control adds an EventHandler for when the Button fires the Click event.

In the OnBubbleClick event, we first check to see if anyone has attached to the event (BubbleClick != null), we can then invoke all the event handling methods by calling BubbleClick, passing through the EventArgs parameter and setting the user control (this) as the event sender. Notice we are also using Response.Write to follow the flow of execution.

An ASPX page can now put the user control to work.
In the code behind for the page.


public class WebForm1 : System.Web.UI.Page
{
protected WebUserControl1 BubbleControl;

private void Page_Load(object sender, System.EventArgs e)
{
Response.Write("WebForm1 :: Page_Load
");
}

#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
InitializeComponent();
base.OnInit(e);
}

private void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);
BubbleControl.BubbleClick += new EventHandler(WebForm1_BubbleClick);
}
#endregion

private void WebForm1_BubbleClick(object sender, EventArgs e)
{
Response.Write("WebForm1 :: WebForm1_BubbleClick from " +
sender.GetType().ToString() + "
");
}
}


Notice the parent page simply needs to add an event handler during InitializeComponent method. When we receive the event we will again use Reponse.Write to follow the flow of execution. When the page executes after clicking on the user control button, you should see the following.




One word of warning: if at anytime events mysteriously stop work, check the InitializeComponent method to make sure the designer has not removed any of the code adding event handlers.


Additional Resources
MSDN: Events and Delegates
MSDN: Raising An Event

1 comment:

Anonymous said...

Hello,

I try to make this example in VS 2005, but the code not work, or work but the event handler always is null, so the event is not raised in the WebUserControl??

public event EventHandler RedondearDecenas;

if (RedondearDecenas != null) //Always Null
{
RedondearDecenas(sender, e);
}

in the page_load:

CtlRedondeo1.RedondearCentenas += new EventHandler(RedondearValores);