
Pro CSharp 2008 And The .NET 3.5 Platform [eng]
.pdf
1232 CHAPTER 32 ■ ASP.NET WEB CONTROLS, THEMES, AND MASTER PAGES
To illustrate working with these validation controls, create a new Web Site project named ValidatorCtrls. To begin, place four (well-named) TextBox types (with four corresponding and descriptive Labels) onto your page. Next, place a RequiredFieldValidator, RangeValidator, RegularExpressionValidator, and CompareValidator type adjacent to each respective field. Finally, add a single Button and final Label (see Figure 32-18).
Figure 32-18. Various validators
Now that you have a UI, let’s walk through the process of configuring each member.
The RequiredFieldValidator
Configuring the RequiredFieldValidator is straightforward. Simply set the ErrorMessage and ControlToValidate properties accordingly using the Visual Studio 2008 Properties window. Here would be the resulting markup to ensure the txtRequiredField text box is not empty:
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ControlToValidate="txtRequiredField" ErrorMessage="Oops! Need to enter data.">
</asp:RequiredFieldValidator>
The RequiredFieldValidator supports an InitialValue property. You can use this property to ensure that the user enters any value other than the initial value in the related TextBox. For example, when the user first posts to a page, you may wish to configure a TextBox to contain the value “Please enter your name”. Now, if you did not set the InitialValue property of the RequiredFieldValidator, the runtime would assume that the string “Please enter your name” is valid. Thus, to ensure a required TextBox is valid only when the user enters anything other than “Please enter your name”, configure your widgets as follows:


1234 CHAPTER 32 ■ ASP.NET WEB CONTROLS, THEMES, AND MASTER PAGES
<asp:CompareValidator ID="CompareValidator1" runat="server" ControlToValidate="txtComparison"
ErrorMessage="Enter a value less than 20." Operator="LessThan" ValueToCompare="20">
</asp:CompareValidator>
Given that the role of this validator is to compare the value in the text box against another value using a binary operator, it should be no surprise that the Operator property may be set to values such as LessThan, GreaterThan, Equal, and NotEqual. Also note that the ValueToCompare is used to establish a value to compare against.
■Note The CompareValidator can also be configured to compare a value within another Web Form control (rather than a hard-coded value) using the ControlToValidate property.
To finish up the code for this page, handle the Click event for the Button type and inform the user he or she has succeeded in the validation logic:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnPostback_Click(object sender, EventArgs e)
{
lblValidationComplete.Text = "You passed validation!";
}
}
Now, navigate to this page using your browser of choice. At this point, you should not see any noticeable changes. However, when you attempt to click the Submit button after entering bogus data, your error message is suddenly visible. Once you enter valid data, the error messages are removed and postback occurs.
If you look at the HTML rendered by the browser, you see that the validation controls generate a client-side JavaScript function that makes use of a specific library of JavaScript functions (contained in the WebUIValidation.js file) that is automatically downloaded to the user’s machine. Once the validation has occurred, the form data is posted back to the server, where the ASP.NET runtime will perform the same validation tests on the web server (just to ensure that no along-the-wire tampering has taken place).
On a related note, if the HTTP request was sent by a browser that does not support client-side JavaScript, all validation will occur on the server. In this way, you can program against the validation controls without being concerned with the target browser; the returned HTML page redirects the error processing back to the web server.
Creating Validation Summaries
The next validation-centric topic we will examine here is the use of the ValidationSummary widget. Currently, each of your validators displays its error message at the exact place in which it was positioned at design time. In many cases, this may be exactly what you are looking for. However, on a complex form with numerous input widgets, you may not want to have random blobs of red text pop up. Using the ValidationSummary type, you can instruct all of your validation types to display their error messages at a specific location on the page.

CHAPTER 32 ■ ASP.NET WEB CONTROLS, THEMES, AND MASTER PAGES |
1235 |
The first step is to simply place a ValidationSummary on your *.aspx file. You may optionally set the HeaderText property of this type as well as the DisplayMode, which by default will list all error messages as a bulleted list.
<asp:ValidationSummary id="ValidationSummary1" runat="server" Width="353px"
HeaderText="Here are the things you must correct."> </asp:ValidationSummary>
Next, you need to set the Display property to None for each of the individual validators (e.g., RequiredFieldValidator, RangeValidator, etc.) on the page. This will ensure that you do not see duplicate error messages for a given validation failure (one in the summary pane and another at the validator’s location). Figure 32-19 shows the summary pane in action.
Figure 32-19. Using a validation summary
Last but not least, if you would rather have the error messages displayed using a client-side
MessageBox, set the ShowMessageBox property to true and the ShowSummary property to false.
Defining Validation Groups
It is also possible to define groups for validators to belong to. This can be very helpful when you have regions of a page that work as a collective whole. For example, you may have one group of controls in a Panel object to allow the user to enter his or her mailing address and another Panel containing UI elements to gather credit card information. Using groups, you can configure each group of controls to be validated independently.
Insert a new page into your current project named ValidationGroups.aspx that defines two Panels. The first Panel object expects a TextBox to contain some form of user input (via a RequiredFieldValidator), while the second Panel expects a US SSN value (via a RegularExpressionValidator). Figure 32-20 shows one possible UI.

1236 CHAPTER 32 ■ ASP.NET WEB CONTROLS, THEMES, AND MASTER PAGES
Figure 32-20. These Panel objects will independently configure their input areas.
To ensure that the validators function independently, simply assign each validator and the control being validated to a uniquely named group using the ValidationGroup property. Here is some possible markup (note that the Click event handlers used here are essentially empty stubs in the code file, and they are only used to allow postback to occur to the web server):
<form id="form1" runat="server">
<asp:Panel ID="Panel1" runat="server" Height="83px" Width="296px"> <asp:TextBox ID="txtRequiredData" runat="server"
ValidationGroup="FirstGroup">
</asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ErrorMessage="*Required field!" ControlToValidate="txtRequiredData"
ValidationGroup="FirstGroup">
</asp:RequiredFieldValidator>
<asp:Button ID="bntValidateRequired" runat="server" OnClick="bntValidateRequired_Click" Text="Validate" ValidationGroup="FirstGroup" />
</asp:Panel>
<asp:Panel ID="Panel2" runat="server" Height="119px" Width="295px"> <asp:TextBox ID="txtSSN" runat="server"
ValidationGroup="SecondGroup">
</asp:TextBox>
<asp:RegularExpressionValidator ID="RegularExpressionValidator1" runat="server" ControlToValidate="txtSSN"
ErrorMessage="*Need SSN" ValidationExpression="\d{3}-\d{2}-\d{4}" ValidationGroup="SecondGroup">
</asp:RegularExpressionValidator> <asp:Button ID="btnValidateSSN" runat="server"
OnClick="btnValidateSSN_Click" Text="Validate"
ValidationGroup="SecondGroup" />
</asp:Panel>
</form>
Now, right-click this page’s designer and select the View In Browser menu option to verify each panel’s widgets operate in a mutually exclusive manner.


1238 CHAPTER 32 ■ ASP.NET WEB CONTROLS, THEMES, AND MASTER PAGES
Understanding *.skin Files
The one file that every theme subdirectory is sure to have is a *.skin file. These files define the look and feel for various web controls. To illustrate, create a new website named FunWithThemes. Next, insert a new *.skin file (using the Web Site Add New Item menu option) named BasicGreen.skin, as shown in Figure 32-22.
Figure 32-22. Inserting *.skin files
Visual Studio 2008 will prompt you to confirm this file can be added into an App_Theme folder (which is exactly what we want). If you were now to look in your Solution Explorer, you would indeed find your App_Theme folder has a subfolder named BasicGreen containing your new
BasicGreen.skin file.
Recall that a *.skin file is where you are able to define the look and feel for various widgets using ASP.NET control declaration syntax. Sadly, the IDE does not provide designer support for *.skin files. One way to reduce the amount of typing time is to insert a temporary *.aspx file into your program (temp.aspx, for example) that can be used to build up the UI of the widgets using the VS 2005 page designer.
The resulting markup can then be copied and pasted into your *.skin file. When you do so, however, you must delete the ID attribute for each web control! This should make sense, given that we are not trying to define a UI look and feel for a particular Button (for example) but all Buttons.
This being said, here is the markup for BasicGreen.skin, which defines a default look and feel for the Button, TextBox, and Calendar types:
<asp:Button runat="server" BackColor="#80FF80"/> <asp:TextBox runat="server" BackColor="#80FF80"/> <asp:Calendar runat="server" BackColor="#80FF80"/>
Notice that each widget still has the runat="server" attribute (which is mandatory), and none of the widgets have been assigned an ID attribute.


1240 CHAPTER 32 ■ ASP.NET WEB CONTROLS, THEMES, AND MASTER PAGES
<pages> element, this will ensure that every page in your website is assigned the selected theme (which is, of course, the name of one of the subdirectories under App_Theme). Here is the core update:
<configuration>
<system.web>
...
<pages theme="BasicGreen">
...
</pages>
</system.web>
</configuration>
If you were to now place various Buttons, Calendars, and TextBoxes onto your Default.aspx file and run the application, you would find each widget has the UI of BasicGreen. If you were to update the theme attribute to CrazyOrange and run the page again, you would find the UI defined by this theme is used instead.
Applying Themes at the Page Level
It is also possible to assign themes on a page-by-page level. This can be helpful in a variety of circumstances. For example, perhaps your web.config file defines a sitewide theme (as described in the previous section); however, you wish to assign a different theme to a specific page. To do so, you can simply update the <%@Page%> directive. If you are using Visual Studio 2008 to do so, you will be happy to find that IntelliSense will display each defined theme within your App_Theme folder.
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="Default.aspx.cs" Inherits="_Default" Theme ="CrazyOrange" %>
Because we assigned the CrazyOrange theme to this page, but the Web.config file specified the BasicGreen theme, all pages but this page will be rendered using BasicGreen.
The SkinID Property
Sometimes you wish to define a set of possible UI look and feels for a single widget. For example, assume you want to define two possible UIs for the Button type within the CrazyOrange theme. When you wish do so, you may differentiate each look and feel using the SkinID property:
<asp:Button runat="server" BackColor="#FF8000"/> <asp:Button runat="server" SkinID = "BigFontButton"
Font-Size="30pt" BackColor="#FF8000"/>
Now, if you have a page that makes use of the CrazyOrange theme, each Button will by default be assigned the unnamed Button skin. If you wish to have various buttons within the *.aspx file make use of the BigFontButton skin, simply specify the SkinID property within the markup:
<asp:Button ID="Button2" runat="server"
SkinID="BigFontButton" Text="Button" /><br />
As an example, Figure 32-24 shows a page that is making use of the CrazyOrange theme. The topmost Button is assigned the unnamed Button skin, while the Button on the bottom of the page has been assigned the SkinID of BigFontButton.
