So far, you've been creating server controls at design time that is, when you build the ASP.NET pages. You can also create them dynamically at runtime when the page is requested from the browser.
What's the difference? Technically, all controls are created at runtime. They're loaded and rendered when the user requests a page. However, design time implementation allows you to set properties of the control before it's requested. When the page is requested, ASP.NET already knows that it must create the control and knows how to do so. With runtime creation, ASP.NET doesn't know that a control must be created until it comes across the code that tells it to do so.
So why would you want to create controls at runtime, when doing so at design-time provides just as much functionality without requiring you to learn any additional syntax? At times, you may not know ahead of time how many controls you need. A typical example is retrieving data from a database. Suppose you want to display the data in an HTML table. Each item will go in its own row. Chances are that you won't know how many items are in the database. Thus, you won't know how many table rows to create ahead of time. Runtime creation solves this problem, allowing you to create as many new rows as needed, when you need them.
Creating built-in controls is just like creating any other object. For example, the following code creates and some properties of a text box control and sets them when the page loads. You don't need to provide the implementation of the control in the HTML portion of the page:
<script language="VB" runat="server"> sub Page_Load(Sender as Object, e as EventArgs) dim objTB as TextBox objTB.ID = "tbOne" objTB.Text = "Hello there!" Page.Controls.Add(objTB) end sub </script>
The objTB text box control will appear in your page when it loads. You can create as many server controls as you want this way. Once a control has been created, it must be added to a container either another control (such as a Panel) or the Page itself. Every control that can contain other controls has a Controls property, which in turn has an Add method that takes the control to add. The previous code snippet produces the output shown in Figure 6.11 when viewed in a browser.
Figure 6.11. Server controls can be added to pages dynamically at runtime.
Note that you can't assign event handlers this way, however. The following will produce an error:
objTB.OnTextChanged = "HandleIt"
Instead, you must add an event handler to this control dynamically, using the AddHandler method in VB.NET:
AddHandler objTB.TextChanged, addressOf HandleIt
The AddHandler method takes two parameters: the event to handle (the TextChanged event in this case not OnTextChanged) and the method that should handle the event. You must use the addressOf operator here. It provides a pointer to the appropriate method. You can now create a HandleIt method that will be executed whenever the TextChanged event fires for this control.
In C#, use the following code:
objTB.TextChanged += new EventHandler(this.HandleIt);
If you want your runtime-created controls to participate in state management, they must be added to a form inside your ASP.NET page. Using Page.Controls.Add won't do this for you. Instead, create a Panel inside <form runat="server"> tags and use PanelID.Controls.Add.
You can use these methods to add custom controls to your pages dynamically as well. The following code snippet shows how to add your third custom control to an ASP.NET page at runtime:
<script runat="server"> dim objCC as new MyCustomControls.CustomControl3 sub Page_Load(Sender as Object, e as EventArgs) objCC.ID = "MyControl" objCC.Message = "Hello world!" Page.Controls.Add(objCC) end sub </script>
Use the namespace name followed by the name of the control to create a new instance, as shown on the second line. (Don't forget to register the control!) The previously described methods won't work with user controls, however. After all, how would you refer to it without a namespace name? The Page.LoadControl method can be used to load a user control dynamically. This method loads your user control from the source file you specify, and it returns an object that reflects the filename. Listing 6.16 shows an example.
Listing 6.16 The LoadControl Method Returns an Object Based on the Filename of the User Control
1: <%@ Page Language="VB" %> 2: <%@ Register TagPrefix="TYASPNET" TagName="LoginForm" src="/books/4/226/1/html/2/LoginForm.ascx" %> 3: 4: <script runat="server"> 5: sub Page_Load(Sender as Object, e as EventArgs) 6: dim objUC as LoginForm_ascx 7: objUC = Page.LoadControl("LoginForm.ascx") 8: objUC.ID = "Control1" 9: objUC.BackColor = "Beige" 10: Panel1.Controls.Add(objUC) 11: 12: lblMessage.Text = "Properties of the user " & _ 13: "control:<br> " & _ 14: "id: " & objUC.id & "<br>" & _ 15: "BackColor: " & objUC.BackColor & "<br>" & _ 16: "Username: " & objUC.Username & "<br>" & _ 17: "Password: " & objUC.Password 18: end sub 19: </script> 20: 21: <html><body> 22: <form runat="server"> 23: <asp:Panel runat="server"/> 24: </form> 25: <p> 26: <asp:Label runat="server" /> 27: </body></html>
| || |
On line 2, you register your user control. This syntax should be familiar by now. Let's examine line 6. You create a new variable objUC of type LoginForm_ascx. Where did this new data type come from? ASP.NET created it from the name of the source file of your user control (LoginForm.ascx) when you registered the control. It simply substituted an underscore for the period, because the period holds special meaning in .NET. This new data type contains all the properties and methods that were declared in your user control, so you can use it to set properties for the control.
On line 7, the LoadControl method creates an instance of your user control from the source file. This method returns an object of type LoginForm_ascx, so your variable objUC can be used to hold the data. On lines 8 and 9, you assign properties just as you did for the dynamically loaded controls you created previously (notice that you only assign the ID and BackColor properties), and on line 10 you add it to the Panel control on line 22. Lines 12 16 display the properties of your control in the label on line 25. When viewed from the browser, this listing will display the image shown in Figure 6.12.
Figure 6.12. The runtime-created control functions just like the design-time control.
You can assign event handlers to user controls just as you did with regular server controls.