Understanding Update Panels With Triggers and Custom Control Events.

In this article I'll explain and demonstrate how to use update panel triggers with custom control events efficiently.


I'll assume you have a minimum knowledge of how Update Panel triggers and user controls work.

Before starting, create an ASP.Net project "UpdatePanelExamples" with a master page. Add a ScriptManager tag in the master page if one does not exist.

Create a separate class library "UpdatePanelLib" in the project (or grab it from the attached source code). Add a reference of this in the web app project.

This library "UpdatePanelLib" contains a custom web control "FooPanel" and a helper class "FooEventHelper".  

The control class "FooPanel" extends a PlaceHolder control.  The Helper class "FooEventHelper" contains helper methods to raise custom events and to search for a specific control on the page.  I added three custom events, "FooEventOne", "FooEventTwo" and "FooEventThree". These events will be raised in the User Controls on some action, such as a button click. Update Panels will subscribe to one or more custom events through triggers. 

The following code shows how to use update panel triggers with control events.

TriggerExample.png

In the code above, "AsyncPostBackTrigger" triggers a data post back to the server when a control with "controlid" fires the "FooEventOne" event.

You can also use a "PostBackTrigger" instead of an "AsyncPostBackTrigger". The only difference is how much data you are posting back. A PostBackTrigger posts back an entire page of data whereas AsyncPostBackTrigger a posts back partial data (in other words the current update panel's data and its dependent controls data if any).

Now, I'll explain and demonstrate a common scenario and  workarounds.

For example, let us assume we have two update panels on a page. Each update panel wraps a user control. Let's say UpdatePanel1 wraps UserControl1 and UpdatePanel2 wraps UserControl2.  Both update panels UpdateMode are set to Conditional. 

UserControl1 contains two buttons "Control1 Button1" and "Control1 Button2" to update the time and a label to show the current time. UserControl2 contains two buttons "Control2 Button1" and "Control2 Button2" and a label to show the current time.

 Scenario1_UI.png

Add a new user  control "UserControl1.ascx" with the following code:

Scenario1_CodeU0.png

Update the following code in UserControl1.ascx.cs:

Scenario1_CodeU1.png

Add a new user control "UserControl2.ascx" with the following code:

Scenario1_CodeU20.png

Update the following code in "UserControl2.ascx.cs":

Scenario1_CodeU2.png

Add a new aspx page "Scenario1.aspx" and set its master page.

Register the following controls in "Scenario1.aspx".

Scenario1_Register.png

Add the following code in "Scenario1.aspx".

Scenario1_Code1.png

Do the following:

a) Build the project and start the page "Scenario1.aspx".

b) Check the times; clicking on the Usercontrol1 buttons updates the UserControl1 time only and the same behavior for UserControl2. Note that the page time will not be updated.

See the action below.

Scenario1_NoChange.gif

Now we want to update the "UserControl2" time when "Control1 Button1" in "UserControl1" is clicked.

We can implement this behavior in one of two ways.

Method 1:

We can expose an event "FooEventOne" in "UserControl1" and other controls can subscribe to this event. We will fire the "FooEventOne" event whenever the user clicks the "Control1 Button1".

The only drawback is if you have 10 or 20 controls then we need to add events to each control. If some controls expose more than one event then it can be a time consuming process.  Each control will have the same copy of the event and as a result there will be a chance of code duplication.  

Do the following.

<!--[if !supportLists]-->a)      <!--[endif]-->Open "UserControl1.ascx.cs" and add the following event handler code.

Scenario1_CodeU11.png


<!--[if !supportLists]-->b)      <!--[endif]-->Add the following code in "btnRefresh_Click" to raise a "FooEventOne" event.

Scenario1_CodeU12.png

<!--[if !supportLists]-->c)       <!--[endif]-->Open "Scenario1.aspx", add a new "AsyncPostBackTrigger" to the triggers for "UpdatePanel2" as in the following:

Scenario1_CodeU1Async.png

<!--[if !supportLists]-->d)      <!--[endif]-->Build and start Scenerio1.aspx.

 

Note the initial timings. Click "Control1 Button1", check UserControl1 and UserControl2 times. They will be the same. Click "Control1 Button2", check the times again. Only the UserControl1 time has changed but not UserControl2.  Because we are firing an event FooEventOne when "Control1 Button1" is clicked and UpdatePanel2 has subscribed to FooEventOne of UserControl1. 


See the action below.

Scenario1_Method1U1.gif


Method 2:

Instead of exposing each event in each control, we can create a parent control "Foo Panel" that wraps specific user control that fires events. This parent control "FooPanel" exposes the required events "FooEventOne", "FooEventTwo" and "FooEventThree".  All the user controls that fire any one of these events must be wrapped by the parent control "FooPanel". 

Using a helper class "FooEventHelper" that exposes RaiseFooEvent method, each user control fires specific event(s) with this method.

This way, we needn't worry about the implementation of the events in each user control. We need to only call the helper "RaiseFooEvent" method to fire an event.

Do the following:

<!--[if !supportLists]-->a)      <!--[endif]-->Open  UserControl1.ascx.cs comment the previous event handler code 

      Comment the code to raise "FooEventOne" in "btnRefresh_Click". Add the code "FooEventHelper.RaiseFooEvent(btnRefresh, FooEvent.FooEventOne, string.Empty)".

Scenario1_CodeM23.png

       Open "Scenario1.aspx", wrap UserControl1 inside FooPanel with id "fooPanel1". Change the "AsyncPostBackTrigger" controlid from "userControl1" to "fooPanel1" in UpdatePanel2 Triggers as in the following.

Scenario1_CodeM21.png

Scenario1_CodeM22.png

b)       Build and start scenerio1.aspx. 

Note the initial timings. Click "Control1 Button1", check UserControl1 and UserControl2 times. They will remain the same. Click "Control1 Button2", check the times again. Only the UserControl1 time has changed but not UserControl2.  Because we are firing an event, FooEventOne, when "Control1 Button1" is clicked and UpdatePanel2 subscribed to FooEventOne of UserControl1. 

See the action below.

Scenario1_Method2U1.gif

Play around by changing events as in the following:

1) Remove the fire event code from the "Control1 Button1" click handler and  add code to the "Control1 Button2" click handler.

2) Remove AsyncPostBackTrigger from UpdatePanel2 and add it to UpdatePanel1 with UserControl2 id and fire an event in the UserControl2 "Control2 Button1" click handler.


In this article, I have explained and demonstrated how to use update panel triggers with custom control events.