ASP.NET Web Forms

 
Chapter 14 - ASP.NET Pages
bySimon Robinsonet al.
Wrox Press 2002
  

As mentioned earlier, much of the functionality in ASP.NET is achieved using Web Forms. Before long we'll dive in and create a simple Web Form to give us a starting point to explore this technology. First, though, we should look at a couple of quick points pertinent to Web Form design. It should be noted that many ASP.NET developers simply use a text editor such as Notepad to create files. This is made easier by the fact that it is possible, as noted earlier, to combine all code in one file. We achieve this by enclosing code in < script > tags, using two attributes on the opening < script > tag as follows :

   <script language="c#" runat="server">     // Server-side code goes here.     </script>   

The runat="server" attribute here is crucial (and we'll see it time and again in this chapter), as it instructs the ASP.NET engine to execute this code on the server rather than sending it to the client, thus giving us access to the rich environment discussed earlier. We can place our functions, event handlers, and so on, in server-side script blocks.

If we omit the runat="server" attribute we are effectively providing client-side code, which will fail if it uses any of the server-side style coding we will see in this chapter. However, there might be times when we want to provide client-side code (indeed, ASP.NET generates some itself sometimes, depending on browser capabilities and what Web Form code is used). Unfortunately we can't use C# here, as to do this would require the .NET Framework on the client, which might not always be the case. Hence JScript is probably the next best option as it is supported on the widest variety of client browsers. To change the language we simply change the value of the language attribute as follows:

   <script language="jscript">     // Client-side code goes here; we can also use "vbscript".     </script>   

It is equally possible to create ASP.NET files in Visual Studio .NET, which is great for us as we are already familiar with this environment for C# programming. However, the default project setup for web applications in this environment has a slightly more complex structure than a single .aspx file. This isn't a problem for us though, and does make things a bit more logical (read: more programmer-like and less web developer-like). Based on this we'll use Visual Studio .NET throughout this chapter for our ASP.NET programming.

.aspx files may also include code in blocks enclosed by < % and % > tags. However, function definitions and variable declarations cannot go here. Instead we can insert code that is executed as soon as the block is reached, which is useful when outputting simple HTML content. This behavior is similar to that of old-style ASP pages, with one important difference: the code is compiled, not interpreted. This results in far better performance.

Now it's time for an example. Create a new project of type ASP.NET Web Application called PCSWebApp1 as shown below:

click to expand

By default, VS.NET will use FrontPage extensions to set up a web application at the required location, which may be remote if your web server is on a different machine. However, it also provides an alternative (and slightly faster) method for doing this, using the file system over a LAN (which is of course impossible if your remote web server isn't on the same LAN as your development server). If the first method fails then VS.NET will try the second.

Regardless of which method is used, VS.NET keeps a local cache of all project files, and keeps these in sync with the files on the web server.

After a few moments Visual Studio .NET should have set up the following:

  • A new solution, PCSWebApp1 , containing the C# Web Application PCSWebApp1

  • AssemblyInfo.cs - the standard VS.NET file describing the assembly

  • Global.asax - application global information and events (see later in this chapter)

  • PCSWebApp1. vsdisco - a file describing any Web Services in the project, enabling dynamic discovery (see next chapter for details)

  • Web.config - configuration information for the application (see later in this chapter)

  • WebForm1.aspx - the first ASP.NET page in the web application

We'll cover all of the generated files over the course of this and the next two chapters; for now we should concentrate on the meat of the application, which is the .aspx file that VS.NET has generated for us.

We can view .aspx files in two ways - in design or code view (well actually it's three, if you count the HTML view in the designer). This is the same as for Windows Forms, as we saw earlier in the book. The initial view in VS.NET is the design view:

click to expand

The text shown in this view by default isn't text that we'll see in our application, it's just a note from VS.NET to say what layout mode is in use. Here we are using GridLayout mode, which allows extra flexibility in control positioning, but we can change this to FlowLayout if we require a more traditional HTML-type positioning scheme. We'll look at this a little later.

If we select the HTML view from the buttons below the layout display we'll see the code generated inside the .aspx file:

   <%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false"     Inherits="PCSWebApp1.WebForm1" %>     <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >     <html>     <head>     <title>WebForm1</title>     <meta name="GENERATOR" Content="Microsoft Visual Studio 7.0">     <meta name="CODE_LANGUAGE" Content="C#">     <meta name="vs_defaultClientScript" content="JavaScript">     <meta name="vs_targetSchema"     content="http://schemas.microsoft.com/intellisense/ie5">     </head>     <body MS_POSITIONING="GridLayout">     <form id="Form1" method="post" Runat="server">     </form>     </body>     </html>   

The < html > element here has been populated with a little metadata that doesn't really concern us, and a < form > element to contain ASP.NET code. The most important thing about this element is the runat attribute. Just as with the server-side code blocks we saw at the start of this section this is set to server , meaning that the processing of the form will take place on the server. If we don't include this then no server-side processing will be performed and the form won't do anything. There can only be one server-side < form > element in an ASP.NET page.

The other interesting thing about this code is the < %@ Page % > tag at the top. This tag defines page characteristics that are important to us as C# web application developers. Firstly there is a language attribute that specifies that we will use C# throughout our page, as we saw earlier with < script > blocks (the default for web applications is VB.NET, although this can be changed using the Web.config configuration file). The next three attributes are necessary, as the code driving the page has been set up by VS.NET to reside in a separate file, WebForm1.aspx.cs . This file, which we'll look at in a moment, contains a class definition that is used as the base class for the Web Forms page. Now we start to see how ASP.NET ties in with a rich object model! This base class will be used in conjunction with code in this file to generate the HTML that reaches the user .

Note that not all .aspx files require this multi-layer model; it is possible just to use the base .NET Web Form class as the base class for the page, which is the default. In this case the .aspx file would include all of our C# code in < script > blocks as mentioned earlier.

Since we are providing a customized base class for the page we might also have customized events. To ensure that the ASP.NET engine is aware of this we use the AutoEventWireup attribute, which signifies whether the Page_Load() event handler (called, surprisingly enough, on loading the page) is automatically wired up to the OnPageLoad event. By setting this attribute to false we must provide our own code to do this if required, but this does allow us a bit more freedom in what we do.

Next we'll look at the "code-behind" code generated for this file. To do this, right-click on WebForm1.aspx in the Solution Explorer and select View Code . This should load the code in WebForm1.aspx.cs into the text editor. First off, we see the default set of namespace references required for basic usagee:

   using System;     using System.Collections;     using System.ComponentModel;     using System.Data;     using System.Drawing;     using System.Web;     using System.Web.SessionState;     using System.Web.UI;     using System.Web.UI.WebControls;     using System.Web.UI.HtmlControls;   

Moving on we see a namespace declaration for our web application followed by the definition of WebForm1 , the base class used for the .aspx page. This class inherits from System.Web.UI.Page , the base class for Web Forms:

   namespace PCSWebApp1     {     /// <summary>     /// Summary description for WebForm1.     /// </summary>     public class WebForm1 : System.Web.UI.Page     {   

The rest of the code in this form performs various initialization tasks , and includes the code required to design Web Forms in VS.NET. No constructor is included (the .NET default one is used), but there is an event handler called Page_Load() that we can use to add any code we require when the page is loaded:

   private void Page_Load(object sender, System.EventArgs e)     {     // Put user code to initialize the page here     }   

The rest of the code is enclosed in a #region block, so to view it we need to expand it:

   #region Web Form Designer generated code     override protected void OnInit(EventArgs e)     {     //     // CODEGEN: This call is required by the ASP.NET Web Form Designer.     //     InitializeComponent();     base.OnInit(e);     }         /// <summary>     /// Required method for Designer support - do not modify     /// the contents of this method with the code editor.     /// </summary>     private void InitializeComponent()     {     this.Load += new System.EventHandler(this.Page_Load);     }     #endregion   

Here the OnInit() event handler inherited from System.Web.UI.Control is overridden. This event handler is executed when the page initializes, and results in InitializeComponent() being called before the base implementation of OnInit() is processed . InitializeComponent() simply wires up the Page_Load() event handler to the Load event of the page, necessary as AutoEventWireup was set to false .

Strictly speaking, this is more code than is required for a simple ASP.NET Web Form page, which can be as simple as we saw right at the start of the chapter (albeit as a trivial example). However, the structure created does lend itself to reusability and expansion using C# techniques, without causing a noticeable amount of overhead, so we'll run with it.

ASP.NET Server Controls

Our generated code doesn't do very much as yet, so next we need to add some content. We can do this in VS.NET using the Web Form designer, which supports drag-and-drop and adding via code in just the same way as the Windows Forms designer.

There are four types of control that we can add to our ASP.NET pages:

  • HTML server controls - controls that mimic HTML elements, which will be familiar to HTML developers.

  • Web server controls - a new set of controls, some of which have the same functionality as HTML controls but with a common naming scheme for properties etc. to ease development, and provide consistency with analogous Windows Forms controls. There are also some completely new and very powerful controls as we will see later.

  • Validation controls - a set of controls capable of performing validation of user input in a simple way.

  • Custom and user controls - controls defined by the developer, which can be defined in a number of ways as we will see in Chapter 16.

    We'll see a complete list of web server and validation controls in the next section, along with usage notes. HTML controls will not be covered in this chapter. These controls don't do anything more than the web server controls, and the web server controls provide a richer environment for those more used to programming than HTML design (which I'm assuming applies to the majority of the audience of this book). Learning how to use the web server controls will provide enough knowledge to use HTML server controls without much difficulty, should you be interested. You could also look at Professional ASP.NET 1.0 ISBN 1-861007-03-5 or ASP.NET Programmer's Reference ISBN 1-861005-30-X, both published by Wrox Press.

Let's add a couple of web server controls to our project. All web server and validation controls are used in the following XML element-type form:

 <asp:  X  runat="server"  attribute="value"  >  Contents  </asp:  X  > 

Where X is the name of the ASP.NET server control, attribute="value" is one or more attribute specifications, and Contents specifies the control content, if any. Some controls allow properties to be set using attributes and control-element content, such as Label (used for simple text display) where Text can be specified in either way. Other controls may use an element containment scheme to define their hierarchy, for example Table (which, spookily enough, defines a table), which can contain TableRow elements in order to specify table rows declaratively .

Note that, as the syntax for controls is based on XML (although they may be used embedded in non-XML code such as HTML), it is an error to omit the closing tags, omit the / > for empty elements, or overlap controls.

Finally, we once again see the runat="server" attribute on web server controls. It is just as essential here as it is elsewhere, and it is a common mistake to miss this attribute off (trust me, you'll do it occasionally), resulting in dead Web Forms.

We'll keep things simple for this first example. Change the HTML design view for WebForm1.aspx as follows:

 <%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false"          Inherits="PCSWebApp1.WebForm1" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" > <html>    <head>       <title>WebForm1</title>       <meta name="GENERATOR" Content="Microsoft Visual Studio 7.0">       <meta name="CODE_LANGUAGE" Content="C#">       <meta name="vs_defaultClientScript" content="JavaScript">       <meta name="vs_targetSchema"             content="http://schemas.microsoft.com/intellisense/ie5">    </head>    <body MS_POSITIONING="GridLayout">       <form id="Form1" method="post" Runat="server">   <asp:Label Runat="server" ID="resultLabel"/><br>     <asp:Button Runat="server" ID="triggerButton" Text="Click Me"/>   </form>    </body> </html> 

Here we have added two web-form controls, a label and a button.

Note that as you do this, VS.NET IntelliSense predicts your code entry just like in C# design.

Going back to the design screen we can see that our controls have been added, and named using their ID attributes. As with Windows Forms we have full access to properties, events, and so on through the Properties window, and can see instant feedback in code or design whenever we make changes.

Next, have another look at WebForm1.aspx.cs . The following two members have been added to our WebForm1 class:

   protected System.Web.UI.WebControls.Button triggerButton;     protected System.Web.UI.WebControls.Label resultLabel;   

Any server controls we add will automatically become part of the object model for our form that we are building in this code-behind file. This is an instant bonus for Windows Forms developers - the similarities are beginning to make themselves known!

To make this application actually do something, let's add an event handler for clicking on the button. Here we can either enter a method name in the Properties window for the button or just double-click on the button to get the default event handler. If we double-click on the button we'll automatically add an event handling method as follows:

   private void triggerButton_Click(object sender, System.EventArgs e)     {     }   

This is hooked up to the button by some code added to InitializeComponent() :

 private void InitializeComponent()       {   this.triggerButton.Click +=     new System.EventHandler(this.triggerButton_Click);   this.Load += new System.EventHandler(this.Page_Load);       } 

Modify the code in triggerButton_Click() as follows:

 protected void triggerButton_Click(object sender, System.EventArgs e)       {   resultLabel.Text = "Button clicked!";   } 

Now we're ready to make it go. Build the application from VS.NET in the normal way and all the files will be compiled and/or placed on the web server ready for use. To test the web application out we can either run the application (which will give us full use of VS.NET debugging facilities), or just point a browser at http://localhost/PCSWebApp1/WebForm1.aspx . Either way you should see the Click Me button on a web page. Before pressing the button, take a quick look at the code received by the browser using View Source (in IE). The < form > section should look something like the following:

   <form name="Form1" method="post" action="WebForm1.aspx" id="Form1">     <input type="hidden" name="__VIEWSTATE" value="dDwtOTk1MjE0NDA4Ozs+" />     <span id="resultLabel"></span><br>     <input type="submit" name="triggerButton" value="Click Me"     id="triggerButton" />     </form>   

The web server controls have generated straight HTML, < span > and < input > for < asp:Label > and < asp:Button >, respectively. There is also a < input type="hidden" > field with the name __VIEWSTATE . This encapsulates the state of the form as mentioned earlier. This information is used when the form is posted back to the server to recreate the UI, keeping track of changes etc. Note that the < form > element has been configured for this; it will post data back to WebForm1.aspx (specified in action ) via an HTTP POST operation (specified in method ). It has also been assigned the name Form1 .

After clicking the button and seeing the text appear, check out the source HTML again (spacing added for clarity below):

   <form name="Form1" method="post" action="WebForm1.aspx" id="Form1">     <input type="hidden" name="__VIEWSTATE"     value="dDwtOTk1MjE0NDA4O3Q8O2w8aTwxPjs+O2w8dDw7bDxpPDE+Oz47bD     x0PHA8cDxsPFRleHQ7PjtsPEJ1dHRvbiBjbGlja2VkITs+Pjs+Ozs+     Oz4+Oz4+Oz4=" />     <span id="resultLabel">Button clicked!</span><br>     <input type="submit" name="triggerButton" value="Click Me"     id="triggerButton" />     </form>   

This time the value of the viewstate contains more information, as the HTML result relies on more than the default output from the ASP.NET page. In complex forms this may be a very long string indeed, but we shouldn't complain, as so much is done for us behind the scenes. We can almost forget about state management, keeping field values between posts, and so on.

The Control Palette

In this section we'll take a quick look at the available controls before we put more of them together into a full, and more interesting, application. We'll divide this section up into web server controls and validation controls. Note that we refer to 'properties' in the control descriptions - in all cases the corresponding attribute for use in ASP.NET code is identically named. We haven't attempted to provide a complete reference here, so we've missed out many properties and only included the most frequently used ones. A complete reference can be found in ASP.NET Programmer's Reference ISBN 1-861005-30-X.

Web Server Controls

Almost all the web server controls inherit from System.Web.UI.WebControls.WebControl , which in turn inherits from System.Web.UI.Control . Those that don't use this inheritance instead derive either directly from Control or from a more specialized base class that derives (eventually) from Control . As such the web server controls have many common properties and events that we can use if required. There are quite a lot of these, so we won't attempt to cover them all here, just as with the properties and events of the web server controls themselves.

Many of the frequently used inherited properties are those that deal with display style. This can be controlled simply, using properties such as ForeColor , BackColor , Font , and so on, but can also be controlled using CSS (Cascading Style Sheet) classes. This is achieved by setting the string property CssClass to the name of a CSS class in a separate file. Other notable properties include Width and Height to size a control, AccessKey and TabIndex to ease user interaction, and Enabled to set whether the control's functionality is activated in the Web Form.

Of the events, we are likely to use the inherited Load event most often, to perform initialization on a control, and PreRender , to perform last-minute modifications before HTML is output by the control.

There are plenty more events and properties for us to make use of, and we'll see many of these in more detail in our later chapter concerning Chapter 16).

The list of web server controls is as follows:

Control

Description

PlaceHolder

This control doesn't render any output, but can be handy for grouping other controls together, or for adding controls programmatically to a given location. Contained controls can be accessed using the Controls property.

Label

Simple text display; use the Text property to set and programmatically modify displayed text.

Literal

Performs the same function as Label , but has no styling properties, just a Text one.

Xml

A more complicated text display control, used for displaying XML content, which may be transformed using an XSLT stylesheet. The XML content is set using one of the Document , DocumentContent , or DocumentSource properties (depending on what format the original XML is in), and the XSLT stylesheet (optional) using either Transform or TransformSource .

TextBox

Provides a textbox that users can edit. Use the Text property to access the entered data, and the TextChanged event to act on selection changes on postback. If automatic postback is required (as opposed to using a button, say) set the AutoPostBack property to true .

DropDownList

Allows the user to select one of a list of choices, either by choosing it directly from a list or typing the first letter or two. Use the Items property to set the item list (this is a ListItemCollection class containing ListItem objects) and the SelectedItem and SelectedIndex properties to determine what is selected. The SelectedIndexChanged event can be used to determine whether the selection has changed, and this control also has an AutoPostBack property so that this selection change will trigger a postback operation.

ListBox

Allows the user to make one or more selections from a list. Set SelectionMode to Multiple or Single to set how many items may be selected at once and Rows to determine how many items to display. Other properties and events as for DropDownList .

Image

Displays an image. Use ImageUrl for the image reference, and AlternateText to provide text if the image fails to load.

AdRotator

Displays several images in succession, with a different one displayed after each server round trip. Use the AdvertisementFile property to specify the XML file describing the possible images and the AdCreated event to perform processing before each image is sent back. Can also use the Target property to name a window to open when an image is clicked.

CheckBox

Displays a box that can be checked or unchecked. The state is stored in the Boolean property Checked , and the text associated with the checkbox in Text . The AutoPostBack property can be used to initiate automatic postback and the CheckedChanged event to act on changes.

CheckBoxList

Creates a group of checkboxes. Properties and events are identical to other list controls, such as DropDownList .

RadioButton

Displays a button that can be turned on or off. Generally these are grouped such that only one in the group can be active. Use the GroupName property to link RadioButton controls into a group. Other properties and events are as per CheckBox .

RadioButtonList

Creates a group of radio buttons where only one button in the group can be selected at a time. Properties and events are as per other list controls.

Calendar

Allows the user to select a date from a graphical calendar display. This control has many style- related properties, but essential functionality can be achieved using the SelectedDate and VisibleDate properties (of type System.DateTime ) to get access to the date selected by the user and the month to display (which will always contain VisibleDate ). The key event to hook up to is SelectionChanged . Postback from this control is automatic.

Button

A standard button for the user to click. Use the Text property for text on the button, and the Click event to respond to clicks (server postback is automatic). Can also use the Command event to respond to clicks, which gives access to additional CommandName and CommandArgument properties on receipt.

LinkButton

Identical to Button , but displays button as a hyperlink.

ImageButton

Displays an image that doubles as a clickable button. Properties and events are inherited from Button and Image .

HyperLink

HTML hyperlink. Set the destination with NavigateUrl and the text to display with Text . You can also use ImageUrl to specify an image to display for the link and Target to specify the browser window to use. This control has no non-standard events, so use a LinkButton instead if additional processing is required when the link is followed.

Table

Specifies a table. Use this in conjunction with TableRow and TableCell at design time or programmatically assign rows using the Rows property, of type TableRowCollection . You can also use this property for run-time modifications. This control has several styling properties unique to tables, as do TableRow and TableCell .

TableRow

Specifies a row within a Table . The key property is Cells , which is a TableCellCollection class containing TableCell objects.

TableCell

Specifies an individual cell within a TableRow . Use Text to set the text to display, Wrap to determine whether to wrap text, and RowSpan and ColumnSpan to set how much of the table is covered by the cell.

Panel

A container for other controls. You can use HorizontalAlign and Wrap to specify how the contents are arranged.

Repeater

Used to output data from a data query, allowing great flexibility using templates. We'll look at this control in detail later in the chapter.

DataList

Similar to the Repeater control, but has more flexibility when it comes to arranging data and formatting. Can automatically render a table, which may be editable, for example. Again, this is a subject for later in the chapter.

DataGrid

Similar to Repeater and DataList with a few extra facilities, such as sorting. See later.

Validation Controls

Validation controls provide a method of validating user input without (in most cases) writing any code at all. Whenever postback is initiated each validation control checks the control it is validating and changes its IsValid property accordingly . If this property is false then the user input for the validated control has failed validation. The page containing all the controls also has an IsValid property - if any of the validation controls has its version of this property set to false then this will be false also. We can check this property from our server-side code and act on it.

However, validation controls have a second function. Not only do they validate controls at run time, they can also output helpful hints to the user automatically. Simply setting the ErrorMessage property to the text you want means the user will see it when they attempt to post back invalid data.

The text stored in ErrorMessage may be output at the point where the validation control is located, or at a separate point, along with the messages from all other validation controls on a page. This latter behavior is achieved using the ValidationSummary control, which displays all error messages along with additional text as required.

On browsers that support it, these controls even generate client-side JavaScript functions to streamline their validation behavior. This means that in some cases postback won't even occur - as the validation controls can prevent this in certain circumstances and output error messages without needing to involve the server.

All validation controls inherit from BaseValidator , and so share several important properties. Perhaps the most important is the ErrorMessage property discussed above, in which case the ControlToValidate property must come a close second. This property specifies the programmatic ID of the control that is being validated. Another important property is Display , which determines whether to place text at the validation summary position (if set to none ), or at the validator position. We also have the choice to make space for the error message even when it's not being displayed (set Display to Static ) or to dynamically allocate space when required, which might shift page contents around slightly (set Display to Dynamic ).

We'll look at an example shortly; first let's briefly describe the various validation controls.

Control

Description

RequiredFieldValidator

Used to check if the user has entered data in a control such as a TextBox .

CompareValidator

Used to check that data entered fulfils simple requirements, by use of an operator set using the Operator property and a ValueToCompare property to validate against. Operator may be one of Equal , GreaterThan , GreaterThanEqual , LessThan , LessThanEqual , NotEqual , and DataTypeCheck . The last of these simply compares the data type of ValueToCompare with the data in the control to be validated. ValueToCompare is a string property, but is interpreted as different data types based on its contents.

RangeValidator

Validates that data in the control to validate falls between MaximumValue and MinimumValue property values.

RegularExpressionValidator

Validates the contents of a field based on a regular expression stored in ValidationExpression . This can be useful for known sequences such as zip codes, phone numbers, IP numbers , and so on.

CustomValidator

Used to validate data in a control using a custom function. ClientValidationFunction is used to specify a client - side function used to validate a control (which means, unfortunately, that we can't use C#). This function should return a Boolean value indicating whether validation was successful. Alternatively, we can use the ServerValidate event to specify a server-side function to use for validation. This function is a bool type event handler that receives a string containing the data to validate instead of an EventArgs parameter. We return true if validation succeeds, otherwise false .

ValidationSummary

Displays validation errors for all validation controls that have an ErrorMessage set. The display can be formatted by setting the DisplayMode ( BulletList , List , or SingleParagraph ) and HeaderText properties. The display can be disabled by setting ShowSummary to false , and displayed in a pop-up message box by setting ShowMessageBox to true .

Server Control Example

Now we've seen what's available to us, and played with a simple example, it's time to look at a more involved scenario. Here we will create the framework for a web application, a meeting room booking tool. For now this will just include the front end and simple event processing; later we will extend this with ADO.NET and data binding to include server-side business logic.

The Web Form we are going to create will contain fields for user name, event name, meeting room, and attendees, along with a calendar to select a date (we're assuming for the purposes of this example that the events last for entire days). We will include validation controls for all fields except the calendar, which we will validate on the server side, and provide a default date in case none has been entered.

For UI testing we will also have a Label control on the form that we can use to display submission results.

To kick things off, create a new web application project in Visual Studio .NET, named PCSWebApp2 . Next we design the form, which is generated using the following code in WebForm1.aspx (with auto-generated code not highlighted):

 <%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false"          Inherits="PCSWebApp2.WebForm1" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" > <html>    <head>       <title>WebForm1</title>       <meta name="GENERATOR" Content="Microsoft Visual Studio 7.0">       <meta name="CODE_LANGUAGE" Content="C#">       <meta name="vs_defaultClientScript" content="JavaScript">       <meta name="vs_targetSchema"             content="http://schemas.microsoft.com/intellisense/ie5">    </head>    <body MS_POSITIONING="GridLayout">       <form id="Form1" method="post" Runat="server">   <h1 align="center">     Enter details and set a day to initiate an event.     </h1>     <br>   

After the title of the page, which is written out enclosed in HTML < h1 > tags to get large, title-style text, the main body of the form is enclosed in an HTML < table >. We could use a web server control table, but this introduces unnecessary complexity as we are using a table purely for formatting the display, not to be a dynamic UI element (an important point to bear in mind when designing Web Forms - don't add web server controls unnecessarily). The table is divided up into three columns , the first holding simple text labels, the second holding UI fields corresponding to the text labels (along with validation controls for these), and the third containing a calendar control for date selection, which spans four rows. The fifth row contains a submission button spanning all columns, and the sixth row contains a ValidationSummary control to display error messages when required (all the other validation controls have Display="None" as they will use this summary for display). Beneath the table is a simple label that we can use to display results for now, before we add database access later.

   <table bordercolor="#000000" cellspacing="0" cellpadding="8"     rules="none" align="center" bgcolor="#fff99e" border="2"     width="540">     <tr>     <td valign="top">Your Name:</td>     <td valign="top">     <asp:TextBox ID="nameBox" Runat="server" Width="160px"/>     <asp:RequiredFieldValidator ID="validateName"     Runat="server"     ErrorMessage="You must enter a name."     ControlToValidate="nameBox"     Display="None"/>     </td>     <td valign="center" rowspan="4">     <asp:Calendar ID="calendar" Runat="server"     BackColor="White"/>     </td>     </tr>     <tr>     <td valign="top">Event Name:</td>     <td valign="top">     <asp:TextBox ID="eventBox" Runat="server" Width="160px"/>     <asp:RequiredFieldValidator ID="validateEvent"     Runat="server"     ErrorMessage="You must enter an event name."     ControlToValidate="eventBox"     Display="None"/>     </td>     </tr>     <tr>   

Most of the ASP.NET code in this file is remarkably simple, and much can be learned simply by reading through it. Of particular note in the code is the way in which list items are attached to the controls for selecting a meeting room and multiple attendees for the event:

   <td valign="top">Meeting Room:</td>     <td valign="top">     <asp:DropDownList ID="roomList" Runat="server" Width="160px">     <asp:ListItem Value="1">The Happy Room</asp:ListItem>     <asp:ListItem Value="2">The Angry Room</asp:ListItem>     <asp:ListItem Value="3">The Depressing Room</asp:ListItem>     <asp:ListItem Value="4">The Funked Out Room</asp:ListItem>     </asp:DropDownList>     <asp:RequiredFieldValidator ID="validateRoom" Runat="server"     ErrorMessage="You must select a room."     ControlToValidate="roomList" Display="None"/>     </td>     </tr>     <tr>     <td valign="top">Attendees:</td>     <td valign="top">     <asp:ListBox ID="attendeeList" Runat="server"     Width="160px"     SelectionMode="Multiple" Rows="6">     <asp:ListItem Value="1">Bill Gates</asp:ListItem>     <asp:ListItem Value="2">Monica Lewinsky</asp:ListItem>     <asp:ListItem Value="3">Vincent Price</asp:ListItem>     <asp:ListItem Value="4">Vlad the Impaler</asp:ListItem>     <asp:ListItem Value="5">Iggy Pop</asp:ListItem>     <asp:ListItem Value="6">William     Shakespeare</asp:ListItem>     </asp:ListBox>   

Here we are associating ListItem objects with the two web server controls. These objects are not web server controls in their own right (they simply inherit from System.Object ), which is why we don't need to use Runat="server" on them. When the page is processed the < asp:ListItem > entries are used to create ListItem objects, which are added to the Items collection of their parent list control. This makes it easier for us to initialize lists than having to write code for this ourselves (we'd have to create a ListItemCollection object, add ListItem objects, and then pass the collection to the list control). Of course, we can still do all of this programmatically if preferred.

   <asp:RequiredFieldValidator ID="validateAttendees"     Runat="server"     ErrorMessage="You must have at least one attendee."     ControlToValidate="attendeeList" Display="None"/>     </td>     </tr>     <tr>     <td align="center" colspan="3">     <asp:Button ID="submitButton" Runat="server" Width="100%"     Text="Submit meeting room request"/>     </td>     </tr>     <tr>     <td align="center" colspan="3">     <asp:ValidationSummary ID="validationSummary"     Runat="server"     HeaderText="Before submitting your request:"/>     </td>     </tr>     </table>     <br>     Results:     <asp:Label Runat="server" ID="resultLabel" Text="None."/>   </form>    </body> </html> 

In design view the form we have created looks like this:

click to expand

This is a fully functioning UI, which maintains its own state between server requests , and validates user input. Considering the brevity of the above code this is quite something. In fact, it leaves us very little to do, at least for this example; we just have to wire up the button click event for the submission button.

Actually, that's not quite true. So far we have no validation for the calendar control. Still, this is simple as it is impossible to clear the selection in this control, so all we have to do is give it an initial value. We can do this in the Page_Load() event handler for our page in the code-behind file:

 private void Page_Load(object sender, System.EventArgs e)       {   if (!this.IsPostBack)     {     calendar.SelectedDate = System.DateTime.Now;     }   } 

Here we just select today's date as a starting point. Note that we first check to see if Page_Load() is being called as the result of a postback operation by checking the IsPostBack property of the page. If a postback is in progress this property will be true and we leave the selected date alone (we don't want to lose the user's selection, after all).

To add the button click handler simply double-click on the button and add the following code:

 private void submitButton_Click(object sender, System.EventArgs e)       {   if (this.IsValid)     {     resultLabel.Text = roomList.SelectedItem.Text +     " has been booked on " +     calendar.SelectedDate.ToLongDateString() +     " by " + nameBox.Text + " for " +     eventBox.Text + " event. ";     foreach (ListItem attendee in attendeeList.Items)     {     if (attendee.Selected)     {     resultLabel.Text += attendee.Text + ", ";     }     }     resultLabel.Text += " and " + nameBox.Text +     " will be attending.";     }   } 

Here we just set the resultLabel control Text property to a result string, which will then appear below the main table. In IE the result of such a submission might look something like the following:

click to expand

unless there are errors, in which case the ValidationSummary will activate instead:

click to expand
  


Professional C#. 2nd Edition
Performance Consulting: A Practical Guide for HR and Learning Professionals
ISBN: 1576754359
EAN: 2147483647
Year: 2002
Pages: 244

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