Build Your Own ASP.NET 2.0 Web Site Using C# & VB, 2nd Edition

from SitePoint


Chapter 4: Constructing ASP.NET Web Pages

If you've ever built a model from Lego bricks, you're well prepared to start building real ASP.NET web pages. ASP.NET offers many techniques that allow web developers to build parts of web pages independently, then put them together later to build complete pages.

The content we're organizing through our work with ASP.NET is almost never static. At design time, we tend to think in terms of templates that contain placeholders for the content that will be generated dynamically at runtime. And to fill those placeholders, we can either use one of the many controls ASP.NET provides, or build our own.

In this chapter, we'll discuss many of the objects and techniques that give life and color to ASP.NET web pages, including:

  • web forms
  • HTML server controls
  • web server controls
  • web user controls
  • master pages
  • handling page navigation
  • styling pages and controls with CSS

If the list looks intimidating, don't worry... all of this is far easier to understand than it might first appear.

Web Forms

As you know, there's always new terminology to master when you're learning new technologies. But with ASP.NET, even the simplest terms that are used to describe the basics of web pages change to reflect the processes that occur within them.

The term used to describe an ASP.NET web page is web form, and this is the central object in ASP.NET development. You've already met web forms--they're the .aspx files you've worked with so far in this book. At first glance, web forms look much like HTML pages, but in addition to static HTML content they also contain ASP.NET presentational elements, and code that executes on the server side to generate dynamic content and perform the desired server-side functionality.

Every web form includes a <form runat="server"> tag, which contains the ASP.NET-specific elements that make up the page. Multiple forms aren't supported. The basic structure of a web form is shown here:

<html>
 <head>
   <script runat="server" language="language">
     ...code here...
   </script>
 </head>
 <body>
   <form runat="server">
     ...user interface elements here...
   </form>
 </body>
</html>

To access and manipulate a web form programatically, we use the System.Web.UI.Page class. You might recognize this class from the code-behind example we saw in Chapter 3, VB and C# Programming Basics. We must mention the class explicitly in the code-behind file. In situations in which we're not using code-behind files (i.e. we write all the code inside the .aspx file instead), the Page class is still used--we just don't see it.

We can use a range of user interface elements inside the form--including typical, static HTML code--but we can also use elements whose values or properties can be generated or manipulated on the server either when the page first loads, or when the form is submitted. These elements--which, in ASP.NET parlance, are called controls--allow us to reuse common functionality, such as the page header, a calendar, a shopping cart summary, or a "Today's Quote" box, for example, across multiple web forms. There are several types of controls in ASP.NET:

  • HTML server controls
  • web server controls
  • web user controls
  • master pages

There are significant technical differences between these types of controls, but what makes them similar is the ease with which we can integrate and reuse them in our web sites. Let's take a look at them one by one.

HTML Server Controls

HTML server controls are outwardly identical to plain old HTML tags, but include a runat="server" attribute. This gives the ASP.NET runtime control over the HTML server controls, allowing us to access them programatically. For example, if we have an <a> tag in a page and we want to be able to change the address to which it links dynamically, using VB or C# code, we use the runat="server" attribute.

A server-side HTML server control exists for each of HTML's most common elements. Creating HTML server controls is easy: we simply stick a runat="server" attribute on the end of a normal HTML tag to create the HTML control version of that tag. The complete list of current HTML control classes and their associated tags is given in Table 4.1.

Table 4.1. HTML control classes
Figure 1: Table 4.1. HTML control classes

For more details on these classes, see Appendix A.

All the HTML server control classes are contained within the System.Web.UI.HtmlControls namespace. As they're processed on the server side by the ASP.NET runtime, we can access their properties through code elsewhere in the page. If you're familiar with JavaScript, HTML, and CSS, then you'll know that manipulating text within HTML tags, or even manipulating inline styles within an HTML tag, can be cumbersome and error-prone. HTML server controls aim to solve these problems by allowing you to manipulate the page easily with your choice of .NET language--for instance, using VB or C#.

Using the HTML Server Controls

Nothing explains the theory better than a simple, working example. Let's create a simple survey form that uses the following HTML server controls:

  • HtmlForm
  • HtmlButton
  • HtmlInputText
  • HtmlSelect

We'll begin by creating a new file named Survey.aspx. Create the file in the Learning folder you created in Chapter 1. The following code creates the visual interface for the survey:

Example 4.1. Survey.aspx (excerpt)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
 <head>
   <title>Using ASP.NET HTML Server Controls</title>
   <!-- code will go here -->
 </head>
 <body>
   <form runat="server">
     <h2>Take the Survey!</h2>
     <!-- Display user name -->
     <p>
       Name:<br />
       <input type="text" id="name" runat="server" />
     </p>
     <!-- Display email -->
     <p>
       Email:<br />
       <input type="text" id="email" runat="server" />
     </p>
     <!-- Display technology options -->
     <p>
       Which server technologies do you use?<br />
       <select id="serverModel" runat="server" multiple="true">
         <option>ASP.NET</option>
         <option>PHP</option>
         <option>JSP</option>
         <option>CGI</option>
         <option>ColdFusion</option>
       </select>
     </p>
     <!-- Display .NET preference options -->
     <p>
       Do you like .NET so far?<br />
       <select id="likeDotNet" runat="server">
         <option>Yes</option>
         <option>No</option>
       </select>
     </p>
     <!-- Display confirmation button -->
     <p>
       <button id="confirmButton" OnServerClick="Click"
           runat="server">Confirm</button>
     </p>
     <!-- Confirmation label -->
     <p>
       <asp:Label id="feedbackLabel" runat="server" />
     </p>
   </form>
 </body>
</html>

From what we've already seen of HTML controls, you should have a good idea of the classes we'll be working with in this page. All we've done is place some HtmlInputText controls, an HtmlButton control, and an HtmlSelect control inside the obligatory HtmlForm control. We've also added a Label control, which we'll use to give feedback to the user.

HTML Server Controls in Action
Remember, HTML server controls are essentially HTML tags with the runat="server" attribute. In most cases, you'll also need to assign them IDs, which will enable you to use the controls in your code.

When it's complete, the Survey.aspx web form will resemble Figure 4.1.

A simple form that uses HTML server controls
Figure 4.1. A simple form that uses HTML server controls

When a user clicks on the button, we'll display the submitted responses in the browser. In a real application, we'd probably be more likely to save this information to a database and perhaps show the results as a chart. Whatever the case, we'd access the properties of the HTML controls as shown below:

Example 4.2. Survey.aspx (excerpt)

<script runat="server" language="VB">
 Sub Click(ByVal s As Object, ByVal e As EventArgs)
   Dim i As Integer
   feedbackLabel.Text = "Your name is: " & name.Value & "<br />"
   feedbackLabel.Text += "Your email is: " & email.Value & _
       "<br />"
   feedbackLabel.Text += "You like to work with:<br />"
   For i = 0 To serverModel.Items.Count - 1
     If serverModel.Items(i).Selected Then
       feedbackLabel.Text += " - " & _
           serverModel.Items(i).Text & "<br />"
     End If
   Next i
   feedbackLabel.Text += "You like .NET: " & likeDotNet.Value
 End Sub
</script>

Example 4.3. Survey.aspx (excerpt)

<script runat="server" language="C#">
 void Click(Object s, EventArgs e)
 {
   feedbackLabel.Text = "Your name is: " + name.Value + "<br />";
   feedbackLabel.Text += "Your email is: " + email.Value +
       "<br />";
   feedbackLabel.Text += "You like to work with:<br />";
   for (int i = 0; i <= serverModel.Items.Count - 1; i++)  
   {
     if (serverModel.Items[i].Selected)  
     {
       feedbackLabel.Text += " - " + serverModel.Items[i].Text +
           "<br />";
     }
   }
   feedbackLabel.Text += "You like .NET: " + likeDotNet.Value;
 }
</script>

As with the examples in previous chapters, we start by placing our VB and C# code inside a server-side script block within the <head> part of the page. Next, we create a new Click event handler that takes the two usual parameters. Finally, we use the Label control to display the user's responses within the page.

Viewing the survey results
Figure 4.2. Viewing the survey results

Once you've written the code, save your work and test the results in your browser. Enter some information and click the button. To select multiple options in the serverModel option box, hold down Ctrl as you click on your preferences. The information you enter should appear at the bottom of the page when the Confirm button is clicked, as shown in Figure 4.2.

In conclusion, working with HTML server controls is really simple. All you need to do is assign each control an ID, and add the runat="server" attribute. Then, you can simply access and manipulate them using VB or C# code on the server side.

Web Server Controls

Web server controls can be seen as more advanced versions of HTML server controls. Web server controls are those that generate content for you--you're no longer in control of the HTML being used. While having good knowledge of HTML is useful, it's not a necessity for those working with web server controls.

Let's look at an example. We can use the Label web server control to place simple text inside a web form. To change the Label's text from within our C# or VB code, we simply set its Text property like so:

myLabel.Text = "Mickey Mouse"

Similarly, to add a text box to our form, we use the TextBox web server control. Again, we can read or set its text using the Text property:

username = usernameTextBox.Text;

Though we're applying the TextBox control, ASP.NET still uses an input element behind the scenes; however, we no longer have to worry about this detail. With web server controls, Microsoft has basically reinvented HTML from scratch.

Unlike HTML server controls, web server controls don't have a direct, one-to-one correspondence with the HTML elements they generate. For example, we can use either of two web server controls--the DropDownList control, or the ListBox control--to generate a select element.

Web server controls follow the same basic pattern as HTML tags, but the tag name is preceded by asp:, and is capitalized using Pascal Casing. Pascal Casing is a form that capitalizes the first character of each word (e.g. TextBox). The object IDs are usually named using Camel Casing, where the first letter of each word except the first is capitalized (e.g. usernameTextBox).

Consider the following HTML input element, which creates an input text box:

<input type="text" name="usernameTextBox" size="30" />

The equivalent web server control is the TextBox control, and it looks like this:

<asp:TextBox id="usernameTextBox" runat="server" Columns="30">
</asp:TextBox>

Remember that, unlike any normal HTML that you might use in your web forms, web server controls are first processed by the ASP.NET engine, where they're transformed to HTML. A side effect of this approach is that you must be very careful to always include closing tags (the </asp:TextBox> part above). The HTML parsers of most web browsers are forgiving about badly formatted HTML code, but ASP.NET is not. Remember that you can use the shorthand /> syntax if nothing appears between your web server control's opening and closing tags. So, you could also write this TextBox like so:

<asp:TextBox id="usernameTextBox" runat="server" Columns="30" />

To sum up, the key points to remember when working with web server controls are:

  • Web server controls must be placed within a <form runat="server"> tag to function properly.
  • Web server controls require the runat="server" attribute to function properly.
  • We include web server controls in a form using the asp: prefix.

There are more web server controls than HTML controls, some offer advanced features that simply aren't available using HTML alone, and some generate quite complex HTML code for you. We'll meet many of the web server controls as we work through this and future chapters.

For more information on web server controls, including the properties, methods, and events for each, have a look at Appendix B.

Standard Web Server Controls

The standard set of web server controls that comes with ASP.NET mirrors the HTML server controls in many ways. However, web server controls offer some new refinements and enhancements, such as support for events and view state, a more consistent set of properties and methods, and more built-in functionality. In this section, we'll take a look as some of the controls you're most likely to use in your day-to-day work.

Remember to use the .NET Framework 2.0 SDK Documentation whenever you need more details about any of the framework's classes (or controls). Access the documentation from Start > All Programs > Microsoft .NET Framework SDK v2.0 > Documentation. To find a class, simply search for the class's name. If there are many classes with a given name in different namespaces, you'll be able to choose the one you want from the Index Results window. For example, you'll find that there are three classes named Label, situated in the System.Web.UI.MobileControls, System.Web.UI.WebControls, and System.Windows.Forms namespaces, as Figure 4.3 illustrates. You'll most likely be interested in the version of the class situated in the WebControls namespace.

Documentation for the Label control
Figure 4.3. Documentation for the Label control

Label

The easiest way to display static text on your page is simply to add the text to the body of the page without enclosing it in any tag. However, if you want to modify the text displayed on a page using ASP.NET code, you can display your text within a Label control. Here's a typical example:

<asp:Label id="messageLabel" Text="" runat="server" />

The following code sets the Text property of the Label control to display the text "Hello World":

Public Sub Page_Load()
 messageLabel.Text = "Hello World"
End Sub

public void Page_Load()  
{
 messageLabel.Text = "Hello World";
}

Reading this Page_Load handler code, we can see that when the page first loads, the Text property of the Label control with the id of message will be set to "Hello World."

Literal

This is perhaps the simplest control in ASP.NET. If you set Literal's Text property, it will simply insert that text into the output HTML code without altering it. Unlike Label, which has similar functionality, Literal doesn't wrap the text in <span> tags that would allow the setting of style information.

TextBox

The TextBox control is used to create a box in which the user can type or read standard text. Using the TextMode property, this control can be set to display text in a single line, across multiple lines, or to hide the text being entered (for instance, in HTML password fields). The following code shows how we might use it in a simple login page:

<p>
 Username: <asp:TextBox id="userTextBox" TextMode="SingleLine"
     Columns="30" runat="server" />
</p>
<p>
 Password: <asp:TextBox id="passwordTextBox"
     TextMode="Password" Columns="30" runat="server" />
</p>
<p>
 Comments: <asp:TextBox id="commentsTextBox"
     TextMode="MultiLine" Columns="30" Rows="10"
     runat="server" />
</p>

In each of the instances above, the attribute TextMode dictates the kind of text box that's to be rendered.

HiddenField

HiddenField is a simple control that renders an input element whose type attribute is set to hidden. We can set its only important property, Value.

Button

By default, the Button control renders an input element whose type attribute is set to submit. When a button is clicked, the form containing the button is submitted to the server for processing, and both the Click and Command events are raised.

The following markup displays a Button control and a Label:

<asp:Button id="submitButton" Text="Submit" runat="server"
   OnClick="WriteText" />
<asp:Label id="messageLabel" runat="server" />

Notice the OnClick attribute on the control. When the button is clicked, the Click event is raised and the WriteText subroutine is called. The WriteText subroutine will contain the code that performs the intended function for this button, such as displaying a message to the user:

Public Sub WriteText(s As Object, e As EventArgs)
 messageLabel.Text = "Hello World"
End Sub

public void WriteText(Object s, EventArgs e)  
{
 messageLabel.Text = "Hello World";
}

It's important to realize that events are associated with most web server controls, and the basic techniques involved in using them, are the same events and techniques we used with the Click event of the Button control. All controls implement a standard set of events because they all inherit from the WebControl base class.

ImageButton

An ImageButton control is similar to a Button control, but it uses an image that we supply in place of the typical system button graphic. Take a look at this example:

<asp:ImageButton id="myImgButton" ImageUrl="myButton.gif"  
   runat="server" OnClick="WriteText" />
<asp:Label id="messageLabel" runat="server" />

The Click event of the ImageButton receives the coordinates of the point at which the image was clicked:

Public Sub WriteText(s As Object, e As ImageClickEventArgs)
 messageLabel.Text = "Coordinate: " & e.X & "," & e.Y
End Sub

public void WriteText(Object s, ImageClickEventArgs e)  
{
 messageLabel.Text = "Coordinate: " + e.X + "," + e.Y;
}

LinkButton

A LinkButton control renders a hyperlink that fires the Click event when it's clicked. From the point of view of ASP.NET code, LinkButtons can be treated in much the same way as buttons, hence the name.

<asp:LinkButton id="myLinkButon" Text="Click Here"
   runat="server" />

HyperLink

The HyperLink control creates on your page a hyperlink that links to the URL in the NavigateUrl property. Unlike the LinkButton control, which offers features such as Click events and validation, HyperLinks are meant to be used to navigate from one page to the next.

<asp:HyperLink id="myLink" NavigateUrl="http://www.sitepoint.com/"
   ImageUrl="splogo.gif" runat="server">SitePoint</asp:HyperLink>

If it's specified, the ImageUrl attribute causes the control to display the specified image, in which case the text is demoted to acting as the image's alternate text.

CheckBox

You can use a CheckBox control to represent a choice that can have only two possible states?checked or unchecked.

<asp:CheckBox id="questionCheck" Text="I agree, I like .NET!"
   Checked="True" runat="server" />

The main event associated with a CheckBox is the CheckChanged event, which can be handled with the OnCheckChanged attribute. The Checked property is True if the checkbox is checked, and False otherwise.

RadioButton

A RadioButton is a lot like a CheckBox, except that RadioButtons can be grouped together to represent a set of options from which only one can be selected. Radio buttons are grouped together using the GroupName property.

<asp:RadioButton id="sanDiego" GroupName="City" Text="San Diego"
   runat="server" /><br />
<asp:RadioButton id="boston" GroupName="City" Text="Boston"  
   runat="server" /><br />
<asp:RadioButton id="phoenix" GroupName="City" Text="Phoenix"  
   runat="server" /><br />
<asp:RadioButton id="seattle" GroupName="City" Text="Seattle"  
   runat="server" />

Like the CheckBox control, the main event associated with RadioButtons is the CheckChanged event, which can be handled with the OnCheckChanged attribute. The other control we can use to display radio buttons is RadioButtonList, which we'll also meet in this chapter.

Image

An Image control creates an image that can be accessed dynamically from code; it equates to the <img> tag in HTML.

Here's an example:

<asp:Image id="myImage" ImageUrl="mygif.gif" runat="server"
   AlternateText="description" />

ImageMap

The ImageMap control generates HTML to display images that have certain clickable regions called hot spots. Each hot spot reacts differently when clicked by the user.

These areas are defined using three controls that generate hot spots of different shapes: CircleHotSpot, RectangleHotSpot, and PolygonHotSpot. Here's an example that defines an image map with two circular hot spots:

<asp:ImageMap ID="myImageMap" runat="server" ImageUrl="image.jpg">
 <asp:CircleHotSpot AlternateText="Button1"
     Radius="20" X="50" Y="50" />
 <asp:CircleHotSpot AlternateText="Button2"
     Radius="20" X="100" Y="50" />
</asp:ImageMap>

Possible values of HotSpotMode, and the bahavior of each, include:

  • Inactive - Exhibits no behavior when hotspot is clicked.
  • Navigate - The user is navigated to the specified URL.
  • NotSet - When set for a HotSpot, the behavior is inherited from the parent ImageMap; if the parent ImageMap doesn't specify a default value, Navigate is set. When set for an ImageMap, this value is effectively equivalent to Navigate.
  • PostBack - The hot spot raises the Click event that can be handled server-side to respond to the user action.

To configure the action that results when a hot spot is clicked by the user, we set the HotSpotMode property of the ImageMap control, or the HotSpotMode property of the individual hot spot objects, or both, using the values shown in the list above. If the HotSpotMode property is set for the ImageMap control as well as for an individual hot spot, the latter property will override that set for the more general ImageMap control.

The Microsoft .NET Framework 2.0 SDK Documentation for the ImageMap class and HotSpotMode enumeration contains detailed examples of the usage of these values.

PlaceHolder

The PlaceHolder control lets us add elements at a particular place on a page at any time, dynamically, through our code.

<asp:PlaceHolder id="placeHolder" runat="server" />

The following code dynamically adds a new HtmlButton control within the placeholder:

Public Sub Page_Load()
 Dim button myButton As HtmlButton = New HtmlButton()
 myButton.InnerText = "My New Button"
 placeHolder.Controls.Add(myButton)
End Sub

public void Page_Load()
{
 HtmlButton button myButton = new HtmlButton();
 myButton.InnerText = "My New Button";
 placeHolder.Controls.Add(myButton);
}

Panel

The Panel control functions similarly to the div element in HTML, in that it allows the set of items that resides within the tag to be manipulated as a group. For instance, the Panel could be made visible or hidden by a Button's Click event:

<asp:Panel id="myPanel" runat="server">
 <p>Username: <asp:TextBox id="usernameTextBox" Columns="30"
     runat="server" /></p>
 <p>Password: <asp:TextBox id="passwordTextBox"
     TextMode="Password" Columns="30" runat="server" />
 </p>
</asp:Panel>
<asp:Button id="hideButton" Text="Hide Panel" OnClick="HidePanel"
   runat="server" />

The code above places two TextBox controls within a Panel control. The Button control is outside of the panel. The HidePanel subroutine would then control the Panel's visibility by setting its Visible property to False:

Public Sub HidePanel(s As Object, e As EventArgs)
 myPanel.Visible = False
End Sub

public void HidePanel(Object s, EventArgs e)  
{
 myPanel.Visible = false;
}

In this case, when the user clicks the button, the Click event is raised and the HidePanel subroutine is called, which sets the Visible property of the Panel control to False.

List Controls

Here, we'll meet the ASP.NET controls that display simple lists of elements: ListBox, DropDownList, CheckBoxList, RadioButtonList, and BulletedList.

DropDownList

A DropDownList control is similar to the HTML select element. The DropDownList control allows you to select one item from a list using a drop-down menu.

<asp:DropDownList id="ddlFavColor" runat="server">
 <asp:ListItem Text="Red" value="red" />
 <asp:ListItem Text="Blue" value="blue" />
 <asp:ListItem Text="Green" value="green" />
</asp:DropDownList>

The most useful event that this control provides is SelectedIndexChanged. This event is exposed by other list controls, such as the CheckBoxList and RadioButtonList controls, allowing for easy programmatic interaction with the control. These controls can also be bound to a database, allowing you to extract dynamic content into a drop-down menu.

ListBox

A ListBox control equates to the HTML select element with either the multiple or size attribute set (size would need to be set to a value of 2 or more). If you set the SelectionMode attribute to Multiple, the user will be able to select more than one item from the list, as in this example:

<asp:ListBox id="listTechnologies" runat="server"
   SelectionMode="Multiple">
 <asp:ListItem Text="ASP.NET" Value="aspnet" />
 <asp:ListItem Text="JSP" Value="jsp" />
 <asp:ListItem Text="PHP" Value="php" />
 <asp:ListItem Text="CGI" Value="cgi" />
 <asp:ListItem Text="ColdFusion" Value="cf" />
</asp:ListBox>

RadioButtonList

Like the RadioButton control, the RadioButtonList control represents radio buttons. However, the RadioButtonList control represents a list of radio buttons and uses more compact syntax. Here's an example:

<asp:RadioButtonList id="favoriteColor" runat="server">
 <asp:ListItem Text="Red" Value="red" />
 <asp:ListItem Text="Blue" Value="blue" />
 <asp:ListItem Text="Green" Value="green" />
</asp:RadioButtonList>

CheckBoxList

As you may have guessed, the CheckBoxList control represents a group of check boxes; it's equivalent to using several CheckBox controls in row:

<asp:CheckBoxList id="favoriteFood" runat="server">
 <asp:ListItem Text="Pizza" Value="pizza" />
 <asp:ListItem Text="Tacos" Value="tacos" />
 <asp:ListItem Text="Pasta" Value="pasta" />
</asp:CheckBoxList>

BulletedList

The BulletedList control displays bulleted or numbered lists, using <ul> (unordered list) or <ol> (ordered list) tags. Unlike the other list controls, the BulletedList doesn't allow the selection of items, so the SelectedIndexChanged event isn't supported.

The first property you'll want to set is DisplayMode, which can be Text (the default), or HyperLink, which will render the list items as links. When DisplayMode is set to HyperLink, you can use the Click event to react when the user clicks on one of the items.

The other important property is BulletStyle, which determines the style of the bullets. The accepted values are Numbered (1, 2, 3, ...), LowerAlpha (a, b, c, ...), UpperAlpha (A, B, C, ...), LowerRoman (i, ii, iii, ...), UpperRoman (I, II, III, ...), Circle, Disc, Square, and CustomImage. If the style is set to CustomImage, you'll also need to set the BulletStyleImageUrl to specify the image to be used for the bullets. If the style is one of the numbered lists, you can also set the FirstBulletNumber property to specify the first number or letter that's to be generated.

Advanced Controls

These controls are advanced in terms of their usage, the HTML code they generate, and the background work they do for you. Some of these controls aren't available to older versions of ASP.NET; we'll learn more about many of them (as well as others that aren't covered in this chapter) as we progress through this book.

Calendar

The Calendar is a great example of the reusable nature of ASP.NET controls. The Calendar control generate the markup to display an intuitive calendar in which the user can click to select or move between days, weeks, months, and so on.

The Calendar control requires very little customization, and can be created within a page like this:

Example 4.4. Calendar.aspx (excerpt)

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"  
   "http://www.w3.org/TR/html4/strict.dtd">
<html>
 <head>
   <title>Calendar Test</title>
 </head>
 <body>
   <form runat="server">
     <asp:Calendar id="myCalendar" runat="server" />
   </form>
 </body>
</html>

If you save this page in the Learning folder and load it, you'd get the output shown in Figure 4.4.

Displaying the default calendar
Figure 4.4. Displaying the default calendar

The Calendar control contains a wide range of properties, methods, and events, including those listed here:

  • DayNameFormat - This property sets the format of the day names. Its possible values are FirstLetter, FirstTwoLetters, Full, and Short. The default is Short, which displays the three-letter abbreviation.
  • FirstDayOfWeek - This property sets the day of the week that begins each week in the calendar. By default, the value of this property is determined by your server's region settings, but you can set this to Sunday or Monday if you want to control it.
  • NextPrevFormat - Set to CustomText by default, this property can be set to ShortMonth or FullMonth to control the format of the next and previous month links.
  • SelectedDate - This property contains a DateTime value that specifies the highlighted day. You'll use this property a lot to determine which day the user has selected.
  • SelectionMode - This property determines whether days, weeks, or months can be selected; its possible values are Day, DayWeek, DayWeekMonth, and None, and the default is Day. When Day is selected, a user can only select a day; when DayWeek is selected, a user can select a day or an entire week; and so on.
  • SelectMonthText - This property controls the text of the link that's displayed to allow users to select an entire month from the calendar.
  • SelectWeekText - This property controls the text of the link that's displayed to allow users to select an entire week from the calendar.
  • ShowDayHeader - If True, this property displays the names of the days of the week. The default is True.
  • ShowGridLines - If True, this property renders the calendar with grid lines. The default is True.
  • ShowNextPrevMonth - If True, this property displays next/previous month links. The default is True.
  • ShowTitle - If True, this property displays the calendar's title. The default is False.
  • TitleFormat - This property determines how the month name appears in the title bar. Possible values are Month and MonthYear. The default is MonthYear.
  • TodaysDate - This DateTime value sets the calendar's current date. By default, this value is not highlighted within the Calendar control.
  • VisibleDate - This DateTime value controls which month is displayed.

Let's take a look at an example that uses some of these properties, events, and methods to create a Calendar control that allows users to select days, weeks, and months. Modify the calendar in Calendar.aspx, and add a label to it, as follows:

Example 4.5. Calendar.aspx (excerpt)

<asp:Calendar ID="myCalendar" runat="server" DayNameFormat="Short"
   FirstDayOfWeek="Sunday" NextPrevFormat="FullMonth"
   SelectionMode="DayWeekMonth" SelectWeekText="Select Week"
   SelectMonthText="Select Month" TitleFormat="Month"
   OnSelectionChanged="SelectionChanged" />
<h2>You selected these dates:</h2>
<asp:Label ID="myLabel" runat="server" />

Now add a <script runat="server"> tag to the head of the web form to include the SelectionChanged event handler referenced by your calendar:

Example 4.6. Calendar.aspx (excerpt)

<script runat="server" language="VB">
 Sub SelectionChanged(ByVal s As Object, ByVal e As EventArgs)
   myLabel.Text = ""
   For Each d As DateTime In myCalendar.SelectedDates
     myLabel.Text &= d.ToString("D") & "<br />"
   Next
 End Sub
</script>

Example 4.7. Calendar.aspx (excerpt)

<script runat="server" language="C#">
 void SelectionChanged(Object s, EventArgs e)
 {
   myLabel.Text = "";
   foreach (DateTime d in myCalendar.SelectedDates)
   {
     myLabel.Text += d.ToString("D") + "<br />";
   }
 }
</script>

Save your work and test it in a browser. Try selecting a day, week, or month. The selection will be highlighted similar to this display shown in Figure 4.5.

Using the Calendar control
Figure 4.5. Using the Calendar control

In SelectionChanged, we loop through each date that the user has selected, and append it to the BulletedList we added to the page.

AdRotator

The AdRotator control allows you to display a list of banner advertisements within your web application at random. However, it's more than a mere substitute for creating a randomization script from scratch. Since the AdRotator control gets its content from an XML file, the administration and updating of banner advertisement files and their properties is a snap. Also, the XML file allows you to control the banner's image, link, link target, and frequency of appearance in relation to other banner ads.

The benefits of using this control don't stop there, though. As most of the AdRotator control's properties reside within an XML file, if you wished, you could share that XML file on the Web, essentially allowing value added resellers (VARS), or possibly your companies' partners, to use your banner advertisements on their web sites.

XML Basics
In essence, XML is simply a text-based format for the transfer or storage of data; it contains no details on how that data should be presented. XML is very easy to start with because of its close resemblance to your old friend HTML: both are largely comprised of tags inside angle brackets (< and >), and any tag may contain attributes specific to that tag. The biggest difference between XML and HTML is that, rather than providing a fixed set of tags as HTML does, XML allows us to create our own tags to describe the data we wish to represent.

Take a look at the following HTML element:

<p>Star Wars Episode I: The Phantom Menace</p>

This example describes the content between the tags as a paragraph. This is fine if all we are concerned with is displaying the words "Star Wars Episode I: The Phantom Menace" on a web page. But what if we want to access those words as data?

Like HTML, XML's purpose is to describe the content of a document. But unlike HTML, XML doesn't describe how that content should be displayed; it describes what the content is. Using XML, the web author can mark up the contents of a document, describing that content in terms of its relevance as data.

We can use XML to mark up the words "Star Wars Episode I: The Phantom Menace" in a way that better reflects this content's significance as data:

<film>
 <title>Star Wars Episode I: The Phantom Menace</title>
</film>

Here, the XML tag names we've chosen best describe the contents of the element. We also define our own attribute names as necessary. For instance, in the example above, you may decide that you want to differentiate between the VHS version and the DVD version of the film, or record the name of the movie's director. This can be achieved by adding attributes and elements, as shown below:

<film format="DVD">
 <title>Star Wars Episode I: The Phantom Menace</title>
 <director>George Lucas</director>
</film>

If you want to test this out, create a file called ads.xml in your Learning folder, and insert the content presented below. Feel free to create your own banners, or to use those provided in the code archive for this book.

Example 4.8. Ads.xml (excerpt)

<Advertisements>
 <Ad>
   <ImageUrl>workatdorknozzle.gif</ImageUrl>
   <NavigateUrl>http://www.dorknozzle.com</NavigateUrl>
   <TargetUrl>_blank</TargetUrl>
   <AlternateText>Work at Dorknozzle.com!</AlternateText>
   <Keyword>HR Sites</Keyword>
   <Impressions>2</Impressions>
 </Ad>
 <Ad>
   <ImageUrl>getthenewsletter.gif</ImageUrl>
   <NavigateUrl>http://www.dorknozzle.com</NavigateUrl>
   <TargetUrl>_blank</TargetUrl>
   <AlternateText>Get the Nozzle Newsletter!</AlternateText>
   <Keyword>Marketing Sites</Keyword>
   <Impressions>1</Impressions>
 </Ad>
</Advertisements>

As you can see, the Advertisements element is the root node, and in accordance with the XML specification, it appears only once. For each individual advertisement, we simply add an Ad child element. For instance, the above advertisement file contains details for two banner advertisements.

As you've probably noticed by now, the .xml file enables you to specify properties for each banner advertisement by inserting appropriate elements inside each of the Ad elements. These elements include:

  • ImageURL - the URL of the image to display for the banner ad
  • NavigateURL - the web page to which your users will navigate when they click the banner ad
  • AlternateText - the alternative text to display for browsers that do not support images
  • Keyword - the keyword to use to categorize your banner ad. If you use the KeywordFilter property of the AdRotator control, you can specify the categories of banner ads to display.
  • Impressions - the relative frequency that a particular banner ad should be shown in relation to other banner advertisements. The higher this number, the more frequently that specific banner will display in the browser. The number provided for this element can be as low as one, but cannot exceed 2,048,000,000; if it does, the page throws an exception.

Except for ImageURL, all these elements are optional. Also, if you specify an Ad without a NavigateURL, the banner ad will display without a hyperlink.

To make use of this Ads.xml file, create a new ASP.NET page, called AdRotator.aspx, with the following code:

Example 4.9. AdRotator.aspx (excerpt)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">  
<html>
 <head>
   <title>AdRotator Control</title>
 </head>
 <body>
   <form runat="server">
     <asp:AdRotator ID="adRotator" runat="server"
         AdvertisementFile="Ads.xml" />
   </form>
 </body>
</html>

You'll need to download workatdorknozzle.gif and getthenewsletter.gif and place them in the Learning folder in order to see these ad images. Save your work and test it in the browser; the display should look something like Figure 4.6.

Displaying ads using AdRotator.aspx
Figure 4.6. Displaying ads using AdRotator.aspx

Refresh the page a few times, and you'll notice that the first banner appears more often than the second. This occurs because the Impression value for the first Ad is double the value set for the second banner, so it will appear twice as often.

TreeView

The TreeView control is a very powerful control that's capable of displaying a complex hierarchical structure of items. Typically we'd use it to view a directory structure or a site navigation hierarchy, but it could be used to display a family tree, a corporate organizational structure, or any other hierarchical structure.

The TreeView can pull its data from various sources. You'll learn more about the various kinds of data sources later in the book; here, we'll focus on the SiteMapDataSource class, which, as its name suggests, contains a hierarchical sitemap. By default, this sitemap is read from a file called Web.sitemap located in the root of your project. The Web.sitemap file is an XML file that looks like this:

Example 4.10. Web.sitemap

<siteMap
   xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0">
 <siteMapNode title="Home" url="~/Default.aspx"
     description="Home">
   <siteMapNode title="TreeViewDemo" url="~/TreeViewDemo.aspx"  
       description="TreeView Example" />
   <siteMapNode title="ClickEvent" url="~/ClickEvent.aspx"
       description="ClickEvent Example" />
   <siteMapNode title="Loops"  url="~/Loops.aspx"
       description="Loops Example" />
 </siteMapNode>
</siteMap>

Web.sitemap Limitation
An important limitation to note when working with Web.sitemap files is that they must contain only one siteMapNode as the direct child of the root siteMap element.

In the example above, the siteMapNode with the title Home is this single siteMapNode. If we added another siteMapNode alongside (rather than inside) this element, the Web.sitemap file would no longer be valid.

To use this file, you'll need to add a SiteMapDataSource control to the page, as well as a TreeView control that uses this data source, like this:

Example 4.11. TreeViewDemo.aspx (excerpt)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">  
<html>
 <head>
   <title>TreeView Demo</title>
 </head>
 <body>
   <form runat="server">
     <asp:SiteMapDataSource ID="mySiteMapDataSource"
         runat="server" />
     <asp:TreeView ID="myTreeView" runat="server"
         DataSourceID="mySiteMapDataSource" />
   </form>
 </body>
</html>

Note that although the SiteMapDataSource is a control, it does not generate any HTML within the web page. There are many data source controls like this; we'll delve into this in more detail later.

When combined with the example Web.sitemap file above, this web form would generate an output such as that shown in Figure 4.7.

A simple TreeView Control
Figure 4.7. A simple TreeView control

As you can see, the TreeView control generated the tree for us. The root Home node can even be collapsed or expanded.

In many cases, we don't want to show the root node; we can hide it from view by setting the ShowStartingNode property of the SiteMapDataSource to false:

<asp:SiteMapDataSource ID="mySiteMapDataSource" runat="server"
   ShowStartingNode="false" />

SiteMapPath

The SiteMapPath control provides the functionality to generate a breadcrumb navigational structure for your site. Breadcrumb systems help to orientate users, giving them an easy way to identify their current location within the site, and provide handy links to the current location's ancestor nodes. An example of a breadcrumb navigation system is shown in Figure 4.8.

A breadcrumb created using the SiteMapPath control
Figure 4.8. A breadcrumb created using the SiteMapPath control

The SiteMapPath control will automatically use any SiteMapDataSource control that exists in a web form to display a user's current location within the site. For example, you could simply add the following code to the form we worked with in the previous example to achieve the effect shown in Figure 4.8:

Example 4.12. TreeViewDemo.aspx (excerpt)

<asp:SiteMapPath id="mySiteMapPath" runat="server"
   PathSeparator=" > ">
</asp:SiteMapPath>

If you run the example now, you'll see the breadcrumb appear exactly as it's shown in Figure 4.8.

Note that the SiteMapPath control shows only the nodes that correspond to existing pages of your site, so if you don't have a file named Default.aspx, the root node link won't show up. Similarly, if the page you're loading isn't named TreeViewDemo.aspx, the SiteMapPath control won't generate any output.

Menu

The Menu control is similar to TreeView in that it displays hierarchical data from a data source; the ways in which we work with both controls are also very similar. The most important differences between the two lie in their appearances, and the fact that Menu supports templates for better customization and displays only two levels of items (menu and submenu items).

MultiView

The MultiView control is similar to Panel in that it doesn't generate interface elements itself, but contains other controls. A MultiView can store more pages of data (called views), and lets you show one page at a time. You can change the active view (the one being presented to the visitor) by setting the value of the ActiveViewIndex property. The first page corresponds to an ActiveViewIndex of 0, the second page is 1, the third page is 2, and so on.

The contents of each template are defined inside child View elements. Consider the following code snippet, which creates a Button control, and a MultiView control:

Example 4.13. MultiViewDemo.aspx (excerpt)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">  
<html>
 <head>
   <title>MultiView Demo</title>
 </head>
 <body>
   <form runat="server">
     <p>
       <asp:Button id="myButton" Text="Switch Page"
           runat="server" OnClick="SwitchPage" />
     </p>
     <asp:MultiView ID="myMultiView" runat="server"
         ActiveViewIndex="0">
       <asp:View ID="firstView" runat="server">
         <p>... contents of the first view ...</p>
       </asp:View>
       <asp:View ID="secondView" runat="server">
         <p>... contents of the second view ...</p>
       </asp:View>
     </asp:MultiView>
   </form>
 </body>
</html>

As you can see, by default, the ActiveViewIndex is 0, so when this code is first executed, the MultiView will display its first template, shown in Figure 4.9.

Using the MultiView control
Figure 4.9. Using the MultiView control

Clicking on the button will cause the second template to be displayed. Here's the code for the SwitchPage event handler:

Example 4.14. MultiViewDemo.aspx (excerpt)

<script runat="server" language="VB">
 Sub SwitchPage(s as Object, e as EventArgs)  
   myMultiView.ActiveViewIndex = _
       (myMultiView.ActiveViewIndex + 1) Mod 2
 End Sub
</script>

Example 4.15. MultiViewDemo.aspx (excerpt)

<script runat="server" language="C#">
 public void SwitchPage(Object s, EventArgs e)  
 {
   myMultiView.ActiveViewIndex =
       (myMultiView.ActiveViewIndex + 1) % 2;
 }
</script>

This simple subroutine uses the modulo operator to set the ActiveViewIndex to 1 when its original value is 0, and vice versa.

The MultiView controls has a number of other handy features, so be sure to check the documentation for this control if you're using it in a production environment.

Wizard

The Wizard control is a more advanced version of the MultiView control. It's able to display one or more pages at a time, but also includes additional built-in functionality such as navigation buttons, and a sidebar that displays the wizard's steps.

FileUpload

The FileUpload control allows you to let visitors upload files to your server. You'll learn how to use this control in Chapter 14, Working with Files and Email.

Web User Controls

As you build real-world projects, you'll frequently encounter pieces of the user interface that appear in multiple places--headers or footers, navigation links, and login boxes are just a few examples. Packaging their forms and behaviors into your own controls will allow you to reuse these components just as you can reuse ASP.NET's built-in controls.

Building your own web server controls involves writing advanced VB or C# code, and is not within the scope of this book, but it's good to know that it's possible. Creating customized web server controls makes sense when you need to build more complex controls that provide a high level of control and performance, or you want to create controls that can be integrated easily into many projects.

Those of us without advanced coding skills can develop our own controls by creating web user controls. These are also powerful and reusable within a given project; they can expose properties, events, and methods, just like other controls; and they're easy to implement.

A web user control is represented by a class that inherits from System.Web.UI.UserControl, and contains the basic functionality that you need to extend to create your own controls. The main drawback to using web user controls is that they're tightly integrated into the projects in which they're implemented. As such, it's more difficult to distribute them, or include them in other projects, than it is to distribute or reuse web server controls.

Web user controls are implemented very much like normal web forms--they're comprised of other controls, HTML markup, and server-side code. The file extension of a web user control is .ascx.

Creating a Web User Control

Let's get a feel for web user controls by stepping through a simple example. Let's say that in your web site, you have many forms consisting of pairs of Label and TextBox controls, like the one shown in Figure 4.10.

A simple form
Figure 4.10. A simple form

All the labels must have a fixed width of 100 pixels, and the text boxes must accept a maximum of 20 characters.

Rather than adding many labels and text boxes to the form, and then having to set all their properties, let's make life easier by building a web user control that includes a Label of the specified width, and a TextBox that accepts 20 characters; you'll then be able to reuse the web user control wherever it's needed in your project.

In your Learning folder, create a new file named SmartBox.ascx. Then, add the control's constituent controls--a Label control and a TextBox control--as shown below:

Example 4.16. SmartBox.ascx (excerpt)

<p>
 <asp:Label ID="myLabel" runat="server" Text="" Width="100" />
 <asp:TextBox ID="myTextBox" runat="server" Text="" Width="200"
     MaxLength="20" />
</p>

Label Widths in Firefox
Unfortunately, setting the Width property of the Label control doesn't guarantee that the label will appear at that width in all browsers. The current version of Firefox, for example, will not display the above label in the way it appears in Internet Explorer.

To get around this, you should use a CSS style sheet and the CssClass property, which we'll take a look at later in this chapter.

In Chapter 3, VB and C# Programming Basics, we discussed properties briefly, but we didn't explain how you could create your own properties within your own classes. So far, you've worked with many properties of the built-in controls. For example, you've seen a lot of code that sets the Text property of the Label control.

As a web user control is a class, it can also have methods, properties, and so on. Our SmartBox control extends the base System.Web.UI.UserControl class by adding two properties:

  • LabelText is a write-only property that allows the forms using the control to set the control's label text.
  • Text is a read-only property that returns the text typed by the user in the text box.

Let's add a server-side script element that will give our control two properties --one called Text, for the text in the TextBox, and one called LabelText, for the text in the Label:

Example 4.17. SmartBox.ascx (excerpt)

<script runat="server" language="VB">
 Public WriteOnly Property LabelText() As String
   Set(ByVal value As String)
     myLabel.Text = value
   End Set
 End Property
 
 Public ReadOnly Property Text() As String
   Get
     Text = myTextBox.Text
   End Get
 End Property
</script>

Example 4.18. SmartBox.ascx (excerpt)

<script runat="server" language="C#">
 public string LabelText  
 {
   set
   {
     myLabel.Text = value;
   }
 }
 public string Text
 {
   get
   {
     return myTextBox.Text;
   }
 }
</script>

Just like web forms, web user controls can work with code-behind files, but, in an effort to keep our examples simple, we aren't using them here. You'll meet more complex web user controls in the chapters that follow.

When you use the SmartBox control in a form, you can set its label and have the text entered by the user, like this:

mySmartBox.LabelText = "Address:"
userAddress = mySmartBox.Text

mySmartBox.LabelText = "Address:";
userAddress = mySmartBox.Text;

Let's see how we implemented this functionality. In .NET, properties can be read-only, write-only, or read-write. In many cases, you'll want to have properties that can be both read and write, but in this case, we want to be able to set the text of the inner Label, and to read the text from the TextBox.

To define a write-only property in VB, you need to use the WriteOnly modifier. Write-only properties need only define a special block of code that starts with the keyword Set. This block of code, called an accessor, is just like a subroutine that takes as a parameter the value that needs to be set. The block of code uses this value to perform the desired action--in the case of the LabelText property, that action sets the Text property of our Label control, as shown below:

Example 4.19. SmartBox.ascx (excerpt)

Public WriteOnly Property LabelText() As String
 Set(ByVal value As String)
   myLabel.Text = value  
 End Set
End Property

Assuming that a form uses a SmartBox object called mySmartBox, we could set the Text property of the Label like this:

mySmartBox.LabelText = "Address:"

When this code is executed, the Set accessor of the LabelText property is executed with its value parameter set to Address:. The Set accessor uses this value to set the Text property of the Label.

The other accessor you can use when defining properties is Get; this allows us to read values instead of writing them. Obviously, you aren't allowed to add a Get accessor to a WriteOnly property, but one is required for a ReadOnly property, such as Text:

Example 4.20. SmartBox.ascx (excerpt)

Public ReadOnly Property Text() As String
 Get
   Text = myTextBox.Text  
 End Get
End Property

The Text property is ReadOnly, but it doesn't need to be. If you wanted to allow the forms using the control to set some default text to the TextBox, you'd need to add a Set accessor, and remove the ReadOnly modifier.

When defining a property in C#, you don't need to set any special modifiers, such as ReadOnly or WriteOnly, for read-only or write-only properties. A property that has only a get accessor will, by default, be considered read-only:

Example 4.21. SmartBox.ascx (excerpt)

public string Text
{
 get
 {
   return myTextBox.Text;
 }
}

Likewise, a property that has only a set accessor will be considered to be write-only:

Example 4.22. SmartBox.ascx (excerpt)

public string LabelText  
{
 set
 {
   myLabel.Text = value;
 }
}

Using the Web User Control

Once the user control has been created, it can be referenced from any ASP.NET page using the Register directive, as follows:

<%@ Register TagPrefix="prefix" TagName="name"
   Src="source.ascx" %>

The Register directive requires three attributes:

  • TagPrefix - the prefix for the user control, which allows you to group related controls together, and avoid naming conflicts
  • TagName - the control's tag name, which will be used when the control is added to the ASP.NET page
  • Src - the path to the .ascx file that describes the user control

After registering the control, we create instances of it using the <TagPrefix:TagName> format. Let's try an example that uses the SmartBox control. Create a new file named ControlTest.aspx in your Learning folder, and give it this content:

Example 4.23. ControlTest.aspx (excerpt)

<%@ Register TagPrefix="sp" TagName="SmartBox"
   Src="SmartBox.ascx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
 <head>
   <title>Creating ASP.NET Web Server Controls</title>
 </head>
 <body>
   <form id="Form1" runat="server">
     <sp:SmartBox id="nameSb" runat="server" LabelText="Name:" />
     <sp:SmartBox id="addressSb" runat="server"
         LabelText="Address:" />
     <sp:SmartBox id="countrySb" runat="server"
         LabelText="Country:" />
     <sp:SmartBox id="phoneSb" runat="server"
         LabelText="Phone:" />
   </form>
 </body>
</html>

Loading this page will produce the output we saw in Figure 4.10.

Now, this is a very simple example indeed, but we can easily extend it for other purposes. You can see in the code snippet that we set the LabelText property directly in the control's tag; we could have accessed the properties from our code instead. Here's an example:

Example 4.24. ControlTest.aspx (excerpt)

<script runat="server" language="VB">
 Protected Sub Page_Load()
   nameSb.LabelText = "Name:"
   addressSb.LabelText = "Address:"
   countrySb.LabelText = "Country:"
   phoneSb.LabelText = "Phone:"
 End Sub
</script>

Example 4.25. ControlTest.aspx (excerpt)

<script runat="server" language="C#">
 protected void Page_Load()
 {
   nameSb.LabelText = "Name:";
   addressSb.LabelText = "Address:";
   countrySb.LabelText = "Country:";
   phoneSb.LabelText = "Phone:";
 }
</script>

Master Pages

Master pages are a new feature of ASP.NET 2.0 that can make an important difference in the way we compose web forms. Master pages are similar to web user controls in that they are also composed of HTML and other controls; they can be extended with the addition of events, methods, or properties; and they can't be loaded directly by users--instead, they're used as building blocks to design the structure of your web forms.

A master page is a page template that can be applied to give many web forms a consistent appearance. For example, a master page can set out a standard structure containing the header, footer, and other elements that you expect to display in multiple web forms within a web application.

Master page files have the .master extension, and, just like web forms and web user controls, they support code-behind files. All master pages inherit from the class System.Web.UI.MasterPage.

Designing a site structure using master pages and web user controls gives you the power to easily modify and extend the site. If your site uses these features in a well-planned way, it can be very easy to modify certain details in the layout or functionality of your site, because updating a master page or a web user control has immediate effects on all the web forms that use the file.

As we've already mentioned, a master page is built using HTML and controls, including the special ContentPlaceHolder control. As its name suggests, the ContentPlaceHolder is a placeholder that can be filled with content relevant to the needs of each web form that uses the master page. In creating a master page, we include all of the basic structure of future pages in the master page itself, including the <html>, <head>, and <body> tags, and let the web forms specify the content that appears in the placeholders.

Let's see how this works with a simple example. Suppose we have a site which has many pages that contain a standard header, footer, and navigation menu, laid out as per the wireframe shown in Figure 4.11.

A simple web site layout
Figure 4.11. A simple web site layout

If all the pages in the site have the same header, footer, and navigation menu, it makes sense to include these components in a master page, and to build several web forms that customize only the content areas on each page. We'll begin to create such a site in Chapter 5, Building Web Applications, but let's work through a quick example here.

To keep this example simple, we won't include a menu here: we'll include just the header, the footer, and the content placeholder. In your Learning folder, create a new file named FrontPages.master, and write the following code into it:

Example 4.26. FrontPages.master (excerpt)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">  
<html>
 <head>
   <title>Front Page</title>
 </head>
 <body>
   <form id="myForm" runat="server">
     <h1>Welcome to SuperSite Inc!</h1>
     <asp:ContentPlaceHolder id="FrontPageContent"
         runat="server" />
     <p>Copyright 2006</p>
   </form>
 </body>
</html>

The master page looks almost like a web form, except for one important detail: it has an empty ContentPlaceHolder control. If you want to build a web form based on this master page, you just need to reference the master page using the Page directive in the web form, and add a Content control that includes the content you want to insert.

Let's try it. Create a web form called FrontPage.aspx, and add this code to it:

Example 4.27. FrontPage.aspx (excerpt)

<%@ Page MasterPageFile="FrontPages.master" %>
<asp:Content id="myContent" runat="server"
   ContentPlaceHolderID="FrontPageContent">
 <p>
   Welcome to our web site! We hope you'll enjoy your visit.
 </p>
</asp:Content>

You're all set now! Loading FrontPage.aspx in your browser will generate the output shown in Figure 4.12.

Using a master page
Figure 4.12. Using a master page

Although the example is simplistic, it's easy to see the possibilities: you can create many web forms based on this template very easily. In our case, the master page contains a single ContentPlaceHolder, but it could have more. Also, the master page can define some default content for display inside the ContentPlaceHolder on pages whose web forms don't provide a Content element for that placeholder.

Using Cascading Style Sheets (CSS)

It's clear that controls make it easy for us to reuse pieces of functionality in multiple places. For example, I can't imagine an easier way to add calendars to many web forms than to use the Calendar web server control.

However, controls don't solve the problem of defining and managing the visual elements of your web site. Modern web sites need constant updating to keep them fresh, and it's not much fun editing hundreds of pages by hand just to change a border color, for example, and then having to check everything to ensure that the changes are consistent. The process is even more painful if the client wants a more serious update, like rearranging components on the pages.

The good news is that this maintenance work can be made a lot easier by planning ahead, correctly following a few basic rules, and efficiently using the tools HTML and ASP.NET offer you.

An essential tool for building reusable visual styles is CSS (Cascading Style Sheets). HTML was initially designed to deliver simple text content, and paid little attention to the specifics of how particular items appeared in the browser. HTML left it to the individual browsers to work out these intricacies, and tailor the output to the limitations and strengths of users' machines. While we can change font styles, sizes, colors, and so on using HTML tags, this practice can lead to verbose code and pages that are very hard to restyle at a later date.

CSS gives web developers the power to create one set of styles in a single location, and to apply those styles to all of the pages in our web site. All the pages to which the style sheet is applied will display the same fonts, colors, and sizes, giving the site a consistent feel. Regardless of whether our site contains three pages or 300, when we alter the styles in the style sheet, our changes are immediately applied to all pages that use the style sheet.

Look out for Themes and Skins
ASP.NET 2.0 provides extra value and power to those building reusable visual elements through its offerings of themes and skins. You'll learn more about these features in Chapter 5, Building Web Applications.

Types of Styles and Style Sheets

There are three different ways in which we can associate styles to the elements of a particular web page:

1. Using an external style sheet

By placing your style rules in an external style sheet, you can link this one file to any web pages on which you want those styles to be used. This makes updating a web site's overall look a cakewalk.

To reference an external style sheet from a web form, insert the following markup inside the head element:

<link rel="stylesheet" type="text/css" href="file.css" />

In the above example, file.css would be a text file containing CSS rules, much like the example shown below:

a
{
 background: #ff9;
 color: #00f;
 text-decoration: underline;
}

2. Using an embedded style sheet

You can place style rules for a page within <style type="text/css"> tags inside that page's head.

<style type="text/css">
 a
 {
   background: #ff9;
   color: #00f;
   text-decoration: underline;
 }
</style>

The problem with using these "embedded" styles is that we can't reuse those styles in another page without having to type them in again, which makes global changes to the site very difficult to manage.

3. Using inline style rules

Inline styles allow us to set styles for a single element using the style attribute. For instance, we might give a paragraph a border, and color it red, with the following markup:

<p style="border-style: groove; color: red;">
 Copyright 2006
</p>

When used in embedded or external style sheets, the first part of any style rule must determine the elements to which the rule will apply; we do this using a selector. In ASP.NET, we typically use two types of selectors:

1. element type selectors

An element type selector targets every single instance of the specified element. For example, if we wanted to change the colour of all level two headers in a document, we'd use an element type selector to target all <h2>s:

h2
{
 color: #369;
}

2. classes

Arguably the most popular way to use styles within your pages is to give each element a class attribute, then target elements that have a certain class value. For example, the following markup shows a paragraph whose class attribute is set to fineprint:

<p class="fineprint">
 Copyright 2006
</p>

Now, given that anything with the class fineprint should be displayed in, well, fine print, we can create a style rule that will reduce the size of the text in this paragraph, and any other element with the attribute class="fineprint":

.fineprint
{
 font-family: Arial;
 font-size: x-small;
}

Whether you're building external style sheets, embedded style sheets, or inline style rules, style declarations use the same syntax.

Now that you have a basic understanding of some of the fundamental concepts behind CSS, let's look at the different types of styles that can be used within our ASP.NET applications.

Style Properties

You can modify many different types of properties using style sheets. Here's a list of the most common property types:

  • font - This category provides you with the ability to format text level elements, including their font faces, sizes, decorations, weights, colors, etc.
  • background - This category allows you to customize backgrounds for objects and text. These values give you control over the background, including whether you'd like to use a color or an image for the background, and whether or not you want to repeat a background image.
  • block - This category allows you to modify the spacing between paragraphs, between lines of text, between words, and between letters.
  • box - The box category allows us to customize tables. If you need to modify borders, padding, spacing, and colors on a table, row, or cell, use the elements within this category.
  • border - This category lets you draw boxes of different colors, styles, and thicknesses around page elements.
  • list - This category allows you to customize the way ordered and unordered lists are created.
  • positioning - Modifying positioning allows you to move and position tags and controls freely.

These categories provide an outline of the aspects of a design that can typically be modified using CSS. As we progress through the book, the many types of style properties will become evident.

The CssClass Property

Once you've defined a class in a style sheet (be it external or internal), you'll want to begin to associate that class with elements in your Web Forms. You can associate classes with ASP.NET Web server controls using the CssClass property. In most cases, the value you give the CssClass property will be used as the value of the resulting element's class attribute.

Let's see an example. First, create in your Learning folder a file named Styles.css, and copy this code into it:

Example 4.28. Styles.css

.title  
{
 font-family: Arial, Helvetica, sans-serif;
 font-size: 19px
}
.dropdownmenu  
{
 font-family: Arial;
 background-color: #0099FF;
}
.textbox  
{
 font-family: Arial;
 background-color: #0099FF;
 border: 1px solid
}
.button  
{
 font-family: Arial;
 background-color: #0099FF;
 border: 1px solid
}

Then, create a new file named UsingStyles.aspx with this code:

Example 4.29. UsingStyles.aspx (excerpt)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
 <head>
   <title>Testing CSS</title>
   <link href="Styles.css" type="text/css" rel="stylesheet" />
 </head>
 <body>
   <form runat="server">
     <p class="title">Please select a product:</p>
     <p>
       <asp:DropDownList id="productsList"  
           CssClass="dropdownmenu" runat="server">
         <asp:ListItem Text="Shirt" selected="true" />
         <asp:ListItem Text="Hat" />
         <asp:Listitem Text="Pants" />
         <asp:ListItem Text="Socks" />
       </asp:DropDownList>
     </p>
     <p>      
       <asp:TextBox id="quantityTextBox" CssClass="textbox"
           runat="server" />
     </p>
     <p>
       <asp:Button id="addToCartButton" CssClass="button"  
           Text="Add To Cart" runat="server"  />
     </p>
   </form>
 </body>
</html>

Loading this page should produce the output shown in Figure 4.13.

CSS at work
Figure 4.13. CSS at work

In the next chapter, we'll learn to use Visual Web Developer to create CSS definitions through a simple visual interface.

Summary

In this chapter, we discussed web forms, HTML server controls, web server controls, web user controls, master pages, and CSS. All these elements can be combined to create powerful structures for your web sites.

In the next chapter, we'll start building "real" web applications, putting into practice most of the theory you've learned so far, and using a professional development environment that will do part of the work for you.


Excerpted from the book "Build Your Own ASP.NET 2.0 Web Site Using C# & VB, 2nd Edition". Learn to create ASP.NET Web sites from scratch using freely available software. Copyright 2006 SitePoint Pty Ltd.


Build Your Own ASP.NET 2.0 Web Site Using C# & VB, 2nd Edition



About the Author

From ASP101

Articles originally posted on ASP101.com

Comments

Leave a Comment

Top White Papers and Webcasts

  • Live Event Date: May 7, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT This eSeminar will explore three popular games engines and how they empower developers to create exciting, graphically rich, and high-performance games for Android® on Intel® Architecture. Join us for a deep dive as experts describe the features, tools, and common challenges using Marmalade, App Game Kit, and Havok game engines, as well as a discussion of the pros and cons of each engine and how they fit into your development …

  • Download the Information Governance Survey Benchmark Report to gain insights that can help you further establish business value in your Records and Information Management (RIM) program and across your entire organization. Discover how your peers in the industry are dealing with this evolving information lifecycle management environment and uncover key insights such as: 87% of organizations surveyed have a RIM program in place 8% measure compliance 64% cannot get employees to "let go" of information for …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds