Recipe 4.5 Adding User Controls Dynamically

     

Recipe 4.5 Adding User Controls Dynamically

4.5.1 Problem

You need to programmatically load a group of user controls at runtime because the number of controls required is not known at design time.

4.5.2 Solution

Bind your data to a Repeater control in the normal fashion and then, as data is bound to each row of the Repeater , use the event to dynamically load a user control and place it in a table cell of the Repeater control's ItemTemplate .

Add a Repeater control to the .aspx file with a table cell in the ItemTemplate where the user control is to be placed.

In the code-behind class, use the .NET language of your choice to:

  1. Bind the data to the Repeater control.

  2. Create an event handler method for the ItemDataBound event of the Repeater control.

  3. In the method that handles the ItemDataBound event, use the LoadControl method to create an instance of the user control, and then add the loaded control to the controls collection of the table cell in the ItemTemplate .

Figure 4-5 shows a simple form where we start with the user controls created in Recipe 4.4 and dynamically load three user controls at runtime. Example 4-24 shows the .aspx file that implements this solution, while Example 4-25 and Example 4-26 show the companion VB and C# code-behind files.

Figure 4-5. User controls loaded at runtime output
figs/ancb_0405.gif

4.5.3 Discussion

This recipe demonstrates how to dynamically load a group of user controls into a form, the count for which can be determined only at runtime. A Repeater control is used because it generates a lightweight read-only tabular display and is template-driven. The Repeater control's ItemTemplate element formats the rows of data. The user control dynamically loaded at runtime is strategically placed in a table cell in the ItemTemplate . This loading takes place in the method that handles the ItemDataBound event for each row of the Repeater . More specifically , the LoadControl method is used to create an instance of the user control, and then the loaded control is added to the controls collection of the table cell.

The example we have written to demonstrate the solution starts with the user controls created in Recipe 4.4 and loads the destination user controls at runtime. In addition, it wires them to the source user control to demonstrate the multicast event mechanism in .NET.

An ASP:Repeater control is placed in the .aspx file with an ItemTemplate containing two table cells . The first cell is used to hold the dynamically loaded user control's number, and the second cell is used to hold the user control itself. Example 4-24 shows how we've implemented this in our example.

The dynamically loaded user controls can be added to the Page control collection; however, this will place them at the bottom of the page and they will be rendered outside of the form. Dynamically loaded user controls should be added to the controls collection of some control contained within the form.


In the repUserControls_ItemDataBound method of the code-behind, the user control for the row being bound is loaded at runtime from the .ascx file using the LoadControl method. It is then added to the controls collection of the second table cell in the Repeater .

Just to demonstrate the multicast event mechanism in .NET that we mentioned in Recipe 4.4, each of the dynamically loaded user controls is wired to the source user control in the .aspx file. This results in each of the dynamically loaded user controls receiving the message event from the source user control.

 
figs/vbicon.gif
 AddHandler ucSource.OnSend, AddressOf ucDest.updateLabel 
figs/csharpicon.gif
 ucSource.OnSend += new CH04UserControlCommSourceCS.customMessageHandler(ucDest.updateLabel); 

The result in this case is that each destination user control is updated with the same text from the source user control ”not very exciting. But it is not hard to imagine a more interesting scenario where one destination user control has a text label updated, the second a database, and the third an XML web service, or the like, with all of these updates the result of methods having been registered with the source control's OnSend event's event handler list.

Example 4-24. User controls loaded at runtime (.aspx)
 <%@ Page Language="vb" AutoEventWireup="false" Codebehind="CH04UserControlRuntimeVB.aspx.vb" Inherits="ASPNetCookbook.VBExamples.CH04UserControlRuntimeVB" %> <%@ Register TagPrefix="ASPCookbook" TagName="SourceControl" Src="CH04UserControlCommSourceVB.ascx" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>Load User Controls At Runtime</title> <link rel="stylesheet" href="css/ASPNetCookbook.css"> </head> <body leftmargin="0" marginheight="0" marginwidth="0" topmargin="0"> <form id="frmUCRuntime" method="post" runat="server"> <table width="100%" cellpadding ="0" cellspacing="0" border="0"> <tr> <td align="center"> <img src="images/ASPNETCookbookHeading_blue.gif"> </td> </tr> <tr> <td class="dividerLine"> <img src="images/spacer.gif" height="6" border="0"></td> </tr> </table> <table width="90%" align="center" border="0"> <tr> <td><img src="images/spacer.gif" height="10" border="0"></td> </tr> <tr> <td align="center" class="PageHeading"> Load User Controls At Runtime (VB) </td> </tr> <tr> <td><img src="images/spacer.gif" height="10" border="0"></td> </tr> <tr> <td align="center"> <table border="0" width="100%"> <tr> <td class="PageHeading" colspan="2"> Source User Control:</td> </tr> <tr> <td bgcolor ="#ffffcc" align="center" height="50" colspan="2"> <ASPCookbook:SourceControl id="ucSource" runat ="server" /> </td> </tr> <tr> <td colspan="2">&nbsp;</td> </tr> <tr> <td class="PageHeading" colspan="2"> User Controls Loaded At Runtime:</td> </tr>  <asp:repeater id="repUserControls" runat="server">   <itemtemplate>   <tr id="trControl" runat="server" height="50">   <td id="tdCount" runat="server" width="10%"></td>   <td id="tdUserControl" runat="server"></td>   </tr>   </itemtemplate>   </asp:repeater>  </table> </td> </tr> </table> </form> </body> </html> 

Example 4-25. User controls loaded at runtime code-behind (.vb)
 Option Explicit On Option Strict On '----------------------------------------------------------------------------- ' ' Module Name : CH04UserControlRuntimeVB.aspx.vb ' ' Description: This module provides the code behind for ' CH04UserControlRuntimeVB.aspx ' '***************************************************************************** Imports System.Collections Imports System.Drawing Imports System.Web.UI.HtmlControls Imports System.Web.UI.WebControls Namespace ASPNetCookbook.VBExamples Public Class CH04UserControlRuntimeVB Inherits System.Web.UI.Page 'controls on the form Protected ucSource As CH04UserControlCommSourceVB Protected WithEvents repUserControls As System.Web.UI.WebControls.Repeater 'the following variable is used to keep count of the number of controls Private controlCount As Integer '************************************************************************* ' ' ROUTINE: Page_Load ' ' DESCRIPTION: This routine provides the event handler for the page load ' event. It is responsible for initializing the ' controls on the page. '------------------------------------------------------------------------- Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles MyBase.Load Dim values As ArrayList = New ArrayList 'build array of data to bind to repeater 'for this example it is just the color of the entry but for a real 'application the data would normally be from a database, etc. values.Add("#ffffcc") values.Add("#ccffff") values.Add("#ccff99") 'bind the data to the repeater controlCount = 0 repUserControls.DataSource = values repUserControls.DataBind( ) End Sub 'Page_Load '************************************************************************* ' ' ROUTINE: repUserControls_ItemDataBound ' ' DESCRIPTION: This routine provides the event handler for the item ' data bound event of the repeater control on the form. ' It is responsible for loading the user control and ' placing it in the repeater for the item being bound. '------------------------------------------------------------------------- Private Sub repUserControls_ItemDataBound(ByVal sender As Object, _ ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) _ Handles repUserControls.ItemDataBound 'the following constants are the names of the controls in the repeater Const TABLE_ROW As String = "trControl" Const COUNT_CELL As String = "tdCount" Const USER_CONTROL_CELL As String = "tdUserControl" Dim row As HtmlTableRow Dim cell As HtmlTableCell Dim ucDest As CH04UserControlCommDestinationVB 'make sure this is an item or alternating item in the repeater If ((e.Item.ItemType = ListItemType.Item) Or _ (e.Item.ItemType = ListItemType.AlternatingItem)) Then 'find the table row and set the background color row = CType(e.Item.FindControl(TABLE_ROW), _ HtmlTableRow) row.BgColor = CStr(e.Item.DataItem) 'find the cell for the control count and set the count cell = CType(e.Item.FindControl(COUNT_CELL), _ HtmlTableCell) controlCount += 1 cell.InnerText = controlCount.ToString( )  'find the cell for the control and load a user control   cell = CType(e.Item.FindControl(USER_CONTROL_CELL), _   HtmlTableCell)   ucDest = CType(LoadControl("CH04UserControlCommDestinationVB.ascx"), _   CH04UserControlCommDestinationVB)   cell.Controls.Add(ucDest)   AddHandler ucSource.OnSend, AddressOf ucDest.updateLabel  End If End Sub 'repUserControls_ItemDataBound End Class 'CH04UserControlRuntimeVB End Namespace 

Example 4-26. User controls loaded at runtime code-behind (.cs)
 //---------------------------------------------------------------------------- // // Module Name: CH04UserControlRuntimeCS.ascx.cs // // Description: This module provides the code behind for // CH04UserControlRuntimeCS.ascx // //**************************************************************************** using ASPNetCookbook.CSExamples; using System; using System.Collections; using System.Drawing; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; namespace ASPNetCookbook.CSExamples { public class CH04UserControlRuntimeCS : System.Web.UI.Page { // controls on the form protected CH04UserControlCommSourceCS ucSource; protected System.Web.UI.WebControls.Repeater repUserControls; // the following variable is used to keep count of the number of controls private int controlCount; //************************************************************************ // // ROUTINE: Page_Load // // DESCRIPTION: This routine provides the event handler for the page // load event. It is responsible for initializing the // controls on the page. //------------------------------------------------------------------------ private void Page_Load(object sender, System.EventArgs e) { ArrayList values = new ArrayList( ); // wire the item data bound event this.repUserControls.ItemDataBound += new RepeaterItemEventHandler(this.repUserControls_ItemDataBound); // build array of data to bind to repeater // for this example it is just the color of the entry but for a real // application the data would normally be from a database, etc. values.Add("#ffffcc"); values.Add("#ccffff"); values.Add("#ccff99"); // bind the data to the repeater controlCount = 0; repUserControls.DataSource = values; repUserControls.DataBind( ); } // Page_Load //************************************************************************ // // ROUTINE: repUserControls_ItemDataBound // // DESCRIPTION: This routine provides the event handler for the item // data bound event of the datalist control in the nav bar. // It is responsible for setting the anchor and image // attributes for the item being bound. //------------------------------------------------------------------------ private void repUserControls_ItemDataBound(Object sender, System.Web.UI.WebControls.RepeaterItemEventArgs e) { // the following constants are the names of the controls in the repeater const String TABLE_ROW = "trControl"; const String COUNT_CELL = "tdCount"; const String USER_CONTROL_CELL = "tdUserControl"; HtmlTableRow row = null; HtmlTableCell cell = null; CH04UserControlCommDestinationCS ucDest = null; // make sure this is an item or alternating item in the repeater if ((e.Item.ItemType == ListItemType.Item)  (e.Item.ItemType == ListItemType.AlternatingItem)) { // find the table row and set the background color row = (HtmlTableRow)(e.Item.FindControl(TABLE_ROW)); row.BgColor = (String)(e.Item.DataItem); // find the cell for the control count and set the count cell = (HtmlTableCell)(e.Item.FindControl(COUNT_CELL)); controlCount += 1; cell.InnerText = controlCount.ToString( );  // find the cell for the control and load a user control   cell = (HtmlTableCell)(e.Item.FindControl(USER_CONTROL_CELL));   ucDest = (CH04UserControlCommDestinationCS)   (LoadControl("CH04UserControlCommDestinationCS.ascx"));   cell.Controls.Add(ucDest);   ucSource.OnSend +=   new   CH04UserControlCommSourceCS.customMessageHandler(ucDest.updateLabel);  } } // repNavBarCell_ItemDataBound } // CH04UserControlRuntimeCS } 



ASP. NET Cookbook
ASP.Net 2.0 Cookbook (Cookbooks (OReilly))
ISBN: 0596100647
EAN: 2147483647
Year: 2006
Pages: 179

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net