Home   |  Articles   |  Resources   |  Humor   |  Feedback       

  Login   Register 


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

Posted by on Saturday, February 14, 2004

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.

<%@ Control Language="c#" AutoEventWireup="false" 
    Codebehind="WebUserControl1.ascx.cs" 
    Inherits="aspnet.eventbubble.WebUserControl1" 
    TargetSchema="http://schemas.microsoft.com/intellisense/ie5"
%>
<asp:Panel id="Panel1" runat="server" Width="128px" Height="96px">
	WebUserControl1 
	<asp:Button id="Button1" Text="Button" runat="server"/>
</asp:Panel>

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 <BR>");
   }

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

   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.

<%@ Register TagPrefix="ksa" 
    TagName="BubbleControl" 
    Src="WebUserControl1.ascx" 
%>
<%@ Page language="c#" Codebehind="WebForm1.aspx.cs" 
    AutoEventWireup="false" Inherits="aspnet.eventbubble.WebForm1" 
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
	<HEAD>
		<title>WebForm1</title>
	</HEAD>
	<body MS_POSITIONING="GridLayout">
		<form id="Form1" method="post" runat="server">
			<ksa:BubbleControl id="BubbleControl" runat="server" />
		</form>
	</body>
</HTML>

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 <BR>");
   }

   #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() + "<BR>");         
   }
}

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

Comments:

bubbling events from ascx's
By ? on 3/30/2004
Thanks for this code! I wish I had it about 6 months ago when, being new to user controls, I went down this path and ran into a wall. I ended up doing MORE work that I would have without them.

I'll check here first next time!

jbh

Nested Control Implementation
By ? on 5/12/2004
Can anyone tell me how this works for a page that references a user control that itself references a user control?

Page_Main.aspx
+ ComplexUserControl.ascx
+ SimpleUserControl.ascx

If SimpleUserControl.ascx raises an event, that event can be captured by ComplexUserControl.ascx, but can it bubble up to the top page without creating an intermediary delegate and event in ComplexUserControl.ascx?

This has been bugging me for ages as I seem to be repeating the same code at each UserControl level just to forward on the event.

Mobile Web Forms
By ? on 5/14/2004
Does this code hold true for mobile web forms as well?

I tried putting it in but I get the following error...

Object reference not set to an instance of an object.

Regarding this line

BubbleControl.BubbleClick += new EventHandler(Test_BubbleClick);

:-S

Oops
By ? on 5/14/2004
My bad!

Had comented out the decleration by mistake.

(Schoolboy shame)

Dynamic User control
By ? on 5/26/2004
How to bubble an event if the usercontrol is created dynamically?

Thanks in advance.

I mean how to take care of this...

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

re: dynamic user control
By scott on 5/27/2004
You'll have to subscribe to the event after loading the control, for example:

private void Page_Load(object sender, System.EventArgs e)
{
WebUserControl1 uc;
uc = LoadControl("WebUserControl1.ascx") as WebUserControl1;
PlaceHolder1.Controls.Add(uc);
uc.BubbleClick += new EventHandler(WebForm1_BubbleClick);
}

This is not Event Bubbling!
By ? on 7/5/2004
Technically the technique in this article is event delegation. Event bubbling is a totally different concept. The idea behind it is that an event from a control bubbles through a containment hierarchy and intercepted through a protected method, called OnBubbleEvent. Then inside the OnBubbleEvent, the parent or the root control determines which child control event, (typically derived from CommandEventArgs) to handle. A bubbled event is not called through a custom event as this article tries to demonstrate.

More dynamic problems
By ? on 8/3/2004
Scott: Awesome article! I have been searching the net for a simple, easy-to-understand tutorial of delegates and events and I have had it with the obscure writing and complex code in the majority of sites. Your little article did the job! Thank you!

With respect to dynamic events and controls, I want to create a table that contains a number of Link and Image Buttons. This table will be created dynamically, based on the source. I have tried your solutions, but I might be missing something. When debugging, the ImageButton_Click method is skipped completely. The relevant code lines are:

public class WebForm1 : System.Web.UI.Page
{
public event ImageClickEventHandler Click;
private void Page_Load(object sender, System.EventArgs e)
{
System.Web.UI.WebControls.ImageButton ibnDrive = new ImageButton ();
ibnDrive.ID = "ibn" + strDrive;
ibnDrive.Click += new ImageClickEventHandler (this.ImageButton_Click);
}

private void ImageButton_Click (object sender, ImageClickEventArgs e)
{
Response.Write("ibnDrive :: Begin ImageButton_Click <BR>");
Response.Write("ibnDrive :: End ImageButton_Click <BR>");
}

Thanks in advance for any assistance.

Taarik.

Can you post source code as files?
By ? on 8/25/2004
Can you put the entire project as a zip folder and post it online so we can download source code directly? I'd really appreciate it.

I'm trying to create a module within a page. This module contains several links which link to other control pages. Problem is, when I click on a link, it will redirect the entire page, instead of just changing the content of the module. Do you think using nested event handling as your site describes might be the solution to this?

Nested Control Implementation
By ? on 9/19/2004
hi scott,

im having the same problem here, i have

default.aspx
menu.ascx
usercontrolbuilder.ascx

how event bubbling relates to this?

tia,
ronnel.santiago

Doesn't work
By ? on 11/13/2004
This concept is great but it doesn't even work...
someone need to revise this !

One more layer of abstraction
By ? on 11/18/2004
What if you don't know what control you are going to load until runtime? Can you inherit those controls from as BaseConrol class (which inherits form UserControl) that exposes the event handlers? I am loading a user control based on user selection. I cant (MyControlType)LoadControl("MyControl.aspx") because I don't know what is is going to be. I would like to be able to do this Panel.Controls.Add((MyBaseControlClass)LoadControl(stringNameOfAscxFile)) and have the event handlers be available to the page that is loading the control. Any ideas?

how to pass a argument
By ? on 1/14/2005
if i want to pass an argument from webcontrol to the aspx page bubble event how would i do it.

very nice article.

thank you

RE: Nested Control Implementation
By ? on 2/28/2005
In a way, yes. If you expose SimpleUserControl as a protected or public property of ComplexUserControl then you can do this,
void Page_Init()
{
ComplexUserControl.SimpleUserControl.Click += Page_Click();
}

Nested Control Implementation
By ? on 3/4/2005
Hello,
Have you find a solution ? I've tried lots of methods but none of them works.

Precompiled.
By ? on 3/8/2005
Thank you for the article. Do the methods here require that the user control be a precompiled class in the bin folder?

DataGrid Check Bubble Event
By ? on 3/11/2005
Can we have the same for the Checkbox check in the datagrid.
I need to performs some operations at the backend after the user clicks a particular row in the datagrid.

Event Bubbling From Web User Controls in ASP.NET (C#)
By ? on 3/15/2005
Thanx
This code is worked in VB.net also. But I have a query regarding bubbling of events.Can anybody let me know about advantages of It?? Also please give any example with code .

My VB.NET code is not running
By ? on 6/20/2005
Can you please give me the VB.NET code, i want to check it, since my VB.NET code is not running.

Copyright 2004 OdeToCode.com 


The Blogs
Subscribe to the OdeToCode blogs for the latest news, downloads, new articles, and quirky commentary.
New Articles
A Software Developer's Guide to HTTP Part V– State & Security
An overview of cookies and authentication protocols for HTTP and web programming.

A Software Developer's Guide to HTTP Part IV– Web Architecture
Proxy servers, caching, and the flexibility of the web are the focus for this article as we view HTTP from an architectural perspective.

A Software Developer's Guide to HTTP Part III–Connections
In this article we'll look at HTTP from a networking perspective, and talk about HTTP connection optimizations like persistent connections and parallel connections.

Most Popular Articles
Table Variables In T-SQL
Table variables allow you to store a resultset in SQL Server without the overhead of declaring and cleaning up a temporary table. In this article, we will highlight the features and advantages of the table variable data type.

AppSettings In web.config
In this article we will review a couple of pratices to keep your runtime configuration information flexible.

ASP.Net 2.0 - Master Pages: Tips, Tricks, and Traps
MasterPages are a great addition to the ASP.NET 2.0 feature set, but are not without their quirks. This article will highlight the common problems developers face with master pages, and provide tips and tricks to use master pages to their fullest potential.

Contribute Code
Privacy
Consultancy