DekGenius.com
[ Team LiB ] Previous Section Next Section

5.3 Using Controls

Server controls have two distinct techniques for using a control in a Web Forms page that can be both useful and confusing: declarative and programmatic techniques. Each has its own purpose, and in some situations (such as when using code-behind), both techniques must be used.

Typically, when you write your pages without code-behind files, you use the declarative technique for using controls in your page. If you need to access those controls programmatically, you would do so by referring to the value of the control's id attribute. For example, if you have an ASP.NET Label control declared as follows:

<asp:label id="Message" runat="server"/>

you would refer to this control in server-side code as follows:

<script runat="server">
   Sub Page_Load( )
      Message.Text = "Hello, World!"
   End Sub
</script>

If you use code-behind with your pages, or if you wish to create a control dynamically at runtime, you may wish to declare and use a control programmatically, as shown here:

Dim Message As New Label( )
Message.Text = "Hello, World!"
Page.Controls.Add(Message)

5.3.1 Declarative Control Use

Declarative control use is the simpler of the two control techniques. Declarative control utilizes HTML-like tags to declare a server control instance and uses attributes to set control properties. The location of the output of the server control is determined by the location of the tag in the page. This technique also allows HTML visual designers to move tags around, if necessary, without impacting the programmatic logic of the page, which would be contained in either a server-side <script> block or in a code- behind class.

Because this technique is so similar to writing plain vanilla HTML (albeit with different tags), it's frequently used by those familiar with classic ASP programming, once they start using server controls. Example 5-1 shows this technique in action, performing an action that in classic ASP would normally be accomplished using Response.Write. The example uses a Literal control which, unlike using Response.Write from a <script> block, allows more precise control of where the rendered output will appear. Instead of writing output to the browser with Response.Write, the code in the Page_Load event handling procedure sets the Text property of the control to the desired output. When the page is rendered, this output is then sent to the browser.

Example 5-1. SimpleWrite.aspx
<%@ Page Language="vb" %>
<html>
<head>
   <title>Declarative Control Example</title>
   <script runat="server">
      Sub Page_Load( )
         'Instead of using Response.Write, we set
         '   the Text property of a literal control.
         '   The placement of the literal control 
         '   determines where output appears
         Message.Text = "This text set from Page_Load!"
      End Sub
   </script>
</head>
<body>
   <form runat="server">
      <asp:literal id="Message" runat="server"/>
   </form>
</body>
</html>

In addition to the precise control of output, another advantage of this technique is better control over the appearance of the rendered output. Developers can use attributes or CSS Styles to modify the appearance of the control, as described later in this chapter in Section 5.6.

5.3.2 Programmatic Control Use

While the declarative technique for control creation is generally simpler and more straightforward, at times you may want or need to create controls dynamically (e.g., in response to some user action). In such cases, developers can create controls programmatically—either in a server-side <script> block within the Web Forms page or in its accompanying code-behind class. You can use either HTML server controls or web controls with this technique.

You define controls programmatically by declaring a variable of the control's type, as shown in the following code snippet (Example 5-2 shows a complete page using this technique):

' Visual Basic .NET
Dim myText As New TextBox( )
  
// C#
TextBox myText = new TextBox( );

The New keyword (new in C#) creates a new instance of the desired control. Note that some controls will accept arguments passed into the constructor for the control. A Literal control, for example, can accept the desired text for the control as an argument passed to the control's constructor, as shown in the following code snippet:

Dim Hello As New Literal("Hello, World!")

Once the desired control instance has been created, the control must then be added to the Controls collection of either the page itself or of a container control on the page that will be rendered (allowing its child controls to be rendered as well). The following snippet shows adding a control named Hello to the Controls collection exposed by the Page object:

Page.Controls.Add(Hello)         ' VB

or:

Page.Controls.Add(Hello);          // C#

It's important to understand that the previous code snippet will add the control named Hello at the end of the Controls collection. This means that the output of the control can actually appear after any static HTML tags because, unless the page contains <% %> render blocks, ASP.NET treats static HTML in the page as Literal controls at runtime. To place a control at a specific point in the page's (or another control's) Controls collection, use the AddAt method instead of Add:

Page.Controls.AddAt(3, Hello)

The first argument to the AddAt method is the position (starting from 0) at which you'd like to add the control, while the second is a variable representing the control itself.

To better understand how ASP.NET renders static HTML, <% %> render blocks, and server controls, turn on tracing for a page (as discussed in Chapter 10) and look at the control tree generated for pages with various combinations of static HTML, server controls, and render blocks. You will find that for pages containing just static HTML, ASP.NET creates a single LiteralControl to represent this HTML on the server. When you add server controls, any static HTML before, after, or between server controls will be represented on the server as a separate LiteralControl. If you add <% %> render blocks, however, controls will not be created on the server for any static HTML. This means that if you wish to manipulate the HTML content of the page on the server, you should avoid using render blocks.

Using the AddAt method, however, may not always allow you to place your control as precisely as you might like. A more precise technique for positioning dynamically created controls on the page is to add a Placeholder control to the page using the declarative technique and then add the dynamically created control(s) to its Controls collection. Because the Placeholder control has no UI of its own, if no controls are added to its Controls collection, nothing is rendered to the browser.

Adding controls dynamically in the middle of a control collection can have unpredictable results when used with pages that post back to the server and maintain their state in ViewState (the default). On postback, the ViewState for controls declared in the Web Forms page is loaded before that of any dynamically created controls. If a control is added to the middle of a control collection, then the page is posted back; you may get errors because the dynamic control for which the ViewState was saved does not exist at the time that ViewState is repopulated.

Example 5-2 shows the use of this technique to create the same output as Example 5-1.

Example 5-2. ProgControl.aspx
<%@ Page Language="vb" %>
<html>
<head>
   <title>Programmatic Control Example</title>
   <script runat="server">
      Sub Page_Init( )
         'The placement of the Placeholder control 
         '   determines where output appears
         Dim Message As New Literal( )
         Message.Text = "This text set from Page_Load!"
         PH.Controls.Add(Message)
      End Sub
   </script>
</head>
<body>
   <form runat="server">
      <asp:placeholder id="PH" runat="server"/>
   </form>
</body>
</html>

Finally, because of the inheritance model used in code-behind pages, if you wish to create controls declaratively in your Web Forms page and manipulate those controls from within a code-behind class, you must programmatically create instances of your controls in the code-behind class with IDs that match those declared in the Web Forms page. For developers using Visual Studio .NET, this is done automatically when you drop a control onto the page from the Visual Studio toolbox (or when switching views in the designer). Example 5-3 shows a Web Forms page that specifies a code-behind page containing its programmatic logic.

Example 5-3. ProgControl_cb.aspx
<%@ Page Language="c#" src="ProgControl_cb.cs" Inherits="aspnetian. ProgControl" %>
<html>
<head>
   <title>Programmatic Control Example using Code-behind</title>
</head>
<body>
   <form runat="server">
      <asp:placeholder id="PH" runat="server"/>
   </form>
</body>
</html>

Example 5-4 shows the code-behind class (written in C#) for the web page in Example 5-3. It creates the control dynamically and adds it to the Controls collection of the PH Placeholder control. Note that the code-behind class declares an instance of the Placeholder class and gives it the same name (ID) as the control declared in the Web Forms page. This allows the code in the code-behind page to manipulate the control at runtime. Also note that this control instance is declared as a protected member, which means that only code within the code-behind class (or classes that inherit from it, including the Web Forms page in Example 5-3) can access it.

Example 5-4. ProgControl_cb.cs
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
  
namespace aspnetian 
{
   public class ProgControl:Page
   {
      protected PlaceHolder PH = new PlaceHolder( );
  
      void Page_Load( )
      {
         // The placement of the Placeholder control 
         //   determines where output appears
         Literal Message = new Literal( );
         Message.Text = "This text set from Page_Load!";
         PH.Controls.Add(Message);
      }
   }
}
    [ Team LiB ] Previous Section Next Section