Dynamic User Controls

Inevitably, you’ll run into a situation in which you want to create an entire User Control dynamically. This often occurs when it is uncertain how many instances of the User Control will be required on your ASP.NET page. Dynamically generated User Controls can be a powerful tool, but you must be aware of a few snags.

Defining a Class Name

To be able to reference the properties and methods of your dynamically loaded User Controls in your ASP.NET page, you must be able to cast them to a strong type. This requires you to define a class name in your User Control definition file. This is a relatively painless process. All it takes is to add a className attribute to the @Control directive, like this:

<%@ Control Language="C#" className="MyControl"%> 

or (Visual Basic .NET)

<%@ Control Language="VB" className=="MyControl" %> 

Failure to specify a className attribute will yield an error that looks like this:

							Compiler Error Message: CS0246: The type or namespace name 'MyControl' could not 
be found (are you missing a using directive or an assembly reference?) 

or (Visual Basic .NET)

							Compiler Error Message: BC30002: Type is not defined: 'MyControl' 

Your User Control is now all set up to be dynamically loaded and cast to a strong type.

Referencing User Control Classes

The code in your ASP.NET page that will dynamically load your User Control changes significantly from the code used to display User Controls using server control tags. Listings 11.13 and 11.14 illustrate what the code should look like:

Listing 11.13. Dynamically Loading User Controls (C#)
<%@ Page Language="C#" %> 
<%@ Reference Control="MyControl_cs.ascx" %> 

<script language="C#" runat="server"> 
     protected void Page_Load(object sender, EventArgs e) 
     {
          MyControl mc1 = (MyControl)LoadControl("MyControl_cs.ascx"); 
          mc1.Name = "Jon"; 
          mc1.DisplayNewDateTime(); 
          panel1.Controls.Add(mc1); 
     } 
</script> 

<html> 
<head><title>MyPage</title></head> 
<body> 
<asp:panel id="panel1" runat="server" /> 
</body> 
</html> 

Listing 11.14. Dynamically Loading User Controls (Visual Basic .NET)
<%@ Page Language="VB" %> 
<%@ Reference Control="MyControl_vb.ascx" %> 

<script language="VB" runat="server"> 
     Protected Sub Page_Load(sender As Object, e As EventArgs) 
          Dim mc1 As MyControl = _ 
               CType(LoadControl("MyControl_vb.ascx"),MyControl) 
          mc1.Name = "Jon" 
          mc1.DisplayNewDateTime() 
          panel1.Controls.Add(mc1) 
     End Sub 
</script> 
<html> 
<head><title>MyPage</title></head> 
<body> 
<asp:panel id="panel1" runat="server" /> 
</body> 
</html> 

Notice the use of the @Reference directive instead of the @Register directive (which is now gone). Because you won’t be adding User Controls as server control tags, you don’t need the @Register directive. The @Reference directive enables you to cast the generic Control object reference returned by the LoadControl method to the specific strong type of your User Control (in this case, MyControl).

Another interesting thing to point out is that the server control tag you used to declare your User Control on the page is now gone, replaced by a Panel server control that serves as a placeholder for your dynamically loaded User Control object.

When Dynamic User Controls Go Wrong

Some interesting things can go wrong if you don’t follow the rules of dynamic User Controls. For instance, if you forget to include the @Register directive, you’ll end up with an error that looks like this:

							Compiler Error Message: CS0246: The type or namespace name 'MyControl' could not 
be found (are you missing a using directive or an assembly reference?) 

or (Visual Basic .NET)

							Compiler Error Message: BC30002: Type is not defined: 'MyControl' 

Likewise, if you forget to cast the generic control object returned by the LoadControl method to the strong type of your User Control, then you’ll see one of these errors:

							Compiler Error Message: CS0029: Cannot implicitly convert type 
'System.Web.UI.Control' to 'ASP.MyControl' 

or (Visual Basic .NET)

							Compiler Error Message: BC30512: Option Strict disallows implicit conversions from 
System.Web.UI.Control to ASP.MyControl. 

Note that the second of these two errors is the Visual Basic flavor and will occur only if you are using the Strict="True" attribute of the @Page directive. Otherwise,Visual Basic will implicitly cast the Control object for you. C# does not offer a setting to turn off option strict, so an explicit cast is always necessary.

If you try to access the properties and methods of a generic Control object returned from the LoadControl method, you’ll get an error message like this:

							Compiler Error Message: CS0117: 'System.Web.UI.Control' does not contain a 
definition for 'Name' 

or (Visual Basic .NET)

							Compiler Error Message: BC30456: The name 'Name' is not a member of
'System.Web.UI.Control'. 

To see the properties and methods specific to your User Control, you must cast it to the proper strong type specified in your @Reference directive.

One final thing to note is that if you want to add multiple instances of your User Control, you must call the LoadControl method for each one. Simply changing the properties of an existing User Control instance and then adding it to the Controls collection of your Panel server control will not suffice; it merely changes the properties of the original User Control that you added. Even though you add the User Control instance to the Panel server control, your variable still maintains a reference to it and can manipulate it.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset