Pro ASP.NET 2.0 In CSharp 2005 (2005) [eng]
.pdf128 C H A P T E R 4 ■ S E R V E R C O N T R O L S
Table 4-12. ListControl Class Properties
Member |
Description |
AutoPostBack |
If true, the form is automatically posted back when the user changes |
|
the current selection. |
Items |
Returns a collection of ListItem items (the items can also be added |
|
declaratively by adding the <asp:ListItem> tag). |
SelectedIndex |
Returns or sets the index of the selected item. For lists with multiple |
|
selectable items, you should loop through the collection of Items and |
|
check the Selected property of each ListItem instead. |
SelectedItem |
Returns a reference to the first selected ListItem. For lists with |
|
multiple selectable items, you should loop through the collection of |
|
Items and check the Selected property of each ListItem instead. |
DataSource |
You can set this property to an object that contains the information |
|
you want to display (such as a DataSet, DataTable, or collection). |
|
When you call DataBind(), the list will be filled based on that object. |
DataMember |
Used in conjunction with data binding when the data source contains |
|
more than one table (such as when the source is a DataSet). The |
|
DataMember identifies which table you want to use. |
DataTextField |
Used in conjunction with data binding to indicate which property or |
|
field in the data source should be used for the text of each list item. |
DataValueField |
Used in conjunction with data binding to indicate which property or |
|
field in the data source should be used for the value attribute of each |
|
list item (which isn’t displayed but can be read programmatically for |
|
future reference). |
DataTextFormatString |
Sets the formatting string used to render the text of the list item |
|
(according to the DataTextField property). |
|
|
In addition, the ListControl control class also defines a SelectedIndexChanged event, which fires when the user changes the current selection.
■Note The SelectedIndexChanged event and the SelectedIndex and SelectedItem properties are not used for the BulletedList control.
The Selectable List Controls
The selectable list controls include the DropDownList, ListBox, CheckBoxList, and RadioButtonList controls—all the list controls except the BulletedList. They allow users to select one or more of the contained items. When the page is posted back, you can check which items were chosen.
By default, the RadioButtonList and CheckBoxList render their interfaces by creating multiple option buttons or check boxes. Both of these classes add a few more properties that allow you to manage the layout of these repeated items, as described in Table 4-13.
C H A P T E R 4 ■ S E R V E R C O N T R O L S |
129 |
Table 4-13. Added RadioButtonList and CheckBoxList Properties
Property |
Description |
RepeatLayout |
This specifies whether the check boxes or radio buttons will be |
|
rendered in a table (the default option) or inline. The values are |
|
Table and Flow, respectively. |
RepeatDirection |
This specifies whether the list of controls will be rendered |
|
horizontally or vertically. |
RepeatColumn |
This sets the number of columns, in case RepeatLayout is set to |
|
Table. |
CellPadding, CellSpacing, |
If RepeatLayout is Table, these properties configure the spacing |
TextAlign |
and alignment of the cells of the layout table. |
|
|
Here’s an example page that declares an instance of every selectable list control, adds items to each of them declaratively, and sets a few other properties:
<form id="form1" runat="server"> <div>
<asp:ListBox runat="server" ID="Listbox1" SelectionMode="Multiple" Rows="5"> <asp:ListItem Selected="true">Option 1</asp:ListItem> <asp:ListItem>Option 2</asp:ListItem>
</asp:ListBox> <br /><br />
<asp:DropDownList runat="server" ID="DropdownList1"> <asp:ListItem Selected="true">Option 1</asp:ListItem> <asp:ListItem>Option 2</asp:ListItem>
</asp:DropDownList> <br /><br />
<asp:CheckBoxList runat="server" ID="CheckboxList1" RepeatColumns="3" > <asp:ListItem Selected="true">Option 1</asp:ListItem> <asp:ListItem>Option 2</asp:ListItem>
</asp:CheckBoxList> <br />
<asp:RadioButtonList runat="server" ID="RadiobuttonList1" RepeatDirection="Horizontal" RepeatColumns="2">
<asp:ListItem Selected="true">Option 1</asp:ListItem> <asp:ListItem>Option 2</asp:ListItem>
</asp:RadioButtonList>
<asp:Button runat="server" Text="Submit" OnClick="Button1_Click"/> </div>
</form>
When the page is loaded for the first time, the event handler for the Page.Load event adds three more items to each list control programmatically, as shown here:
protected void Page_Load(object sender, System.EventArgs e)
{
if (!Page.IsPostBack)
{
for (int i=3; i<=5; i++)
{
130 C H A P T E R 4 ■ S E R V E R C O N T R O L S
Listbox1.Items.Add("Option " + i.ToString()); DropdownList1.Items.Add("Option " + i.ToString()); CheckboxList1.Items.Add("Option " + i.ToString()); RadiobuttonList1.Items.Add("Option " + i.ToString());
}
}
}
Finally, when the submit button is clicked, the selected items of each control are displayed on the page. For the controls with a single selection (DropDownList and RadioButtonList), this is just a matter of accessing the SelectedItem property. For the other controls that allow multiple selections, you must cycle through all the items in the Items collection and check whether the ListItem.Selected property is true. Here’s the code that does both of these tasks:
protected void Button1_Click(object sender, System.EventArgs e)
{
Response.Write("<b>Selected items for Listbox1:</b><br />"); foreach (ListItem li in Listbox1.Items)
{
if (li.Selected) Response.Write("- " + li.Text + "<br />");
}
Response.Write("<b>Selected item for DropdownList1:</b><br />");
Response.Write("- " + DropdownList1.SelectedItem.Text + "<br />");
Response.Write("<b>Selected items for CheckboxList1:</b><br />"); foreach (ListItem li in CheckboxList1.Items)
{
if (li.Selected) Response.Write("- " + li.Text + "<br />");
}
Response.Write("<b>Selected item for RadiobuttonList1:</b><br />"); Response.Write("- " + RadiobuttonList1.SelectedItem.Text + "<br />");
}
To test the page, load it, select one or more items in each control, and then click the button. You should get something like what’s shown in Figure 4-10.
■Tip You can set the ListItem.Disabled property to true if you want an item in a RadioButtonList or CheckBoxList to be disabled. It will still appear in the page, but it will be grayed out and won’t be selectable. The ListItem.Disabled is ignored for ListBox and DropDownList controls.
The BulletedList Control
The BulletedList control is the server-side equivalent of the <ul> (unordered list) or <ol> (ordered list) elements. As with all list controls, you set the collection of items that should be displayed through the Items property. Additionally, you can use the properties in Table 4-14 to configure how the items are displayed.
C H A P T E R 4 ■ S E R V E R C O N T R O L S |
131 |
Figure 4-10. Checking for selected items in the list controls
Table 4-14. Added BulletedList Properties
Property |
Description |
BulletStyle |
Determines the type of list. Choose from Numbered (1, 2, 3…), |
|
LowerAlpha (a, b, c…) and UpperAlpha (A, B, C…), LowerRoman |
|
(i, ii, iii…) and UpperRoman (I, II, III…), and the bullet symbols Disc, |
|
Circle, Square, or CustomImage (in which case you must set the |
|
BulletStyleImageUrl property). |
BulletStyleImageUrl |
If the BulletStyle is set to Custom, this points to the image that is placed |
|
to the left of each item as a bullet. |
FirstBulletNumber |
In an ordered list (using the Numbered, LowerAlpha, UpperAlpha, |
|
LowerRoman, or UpperRoman styles) this sets the first value. For |
|
example, if you set FirstBulletNumber to 3, the list might read 3, 4, 5 |
|
(for Numbered) or C, D, E (for UpperAlpha). |
DisplayMode |
Determines whether the text of each item is rendered as text (use Text, |
|
the default) or a hyperlink (use HyperLink). |
|
|
132 C H A P T E R 4 ■ S E R V E R C O N T R O L S
If you choose to set the DisplayMode to use hyperlinks, you can react to the Click event to determine which item was clicked. Here’s an example:
protected void BulletedList1_Click(object sender, BulletedListEventArgs e)
{
string itemText = BulletedList1.Items[e.Index].Text; Label1.Text = "You choose item" + itemText;
}
Figure 4-11 shows the different DisplayMode values. When you click one, the list is updated accordingly.
Figure 4-11. Different BulletedList styles
Input Validation Controls
One of the most common uses for web pages (and the reason that the HTML form tags were first created) is to collect data. Often, a web page will ask a user for some information and then store it in a back-end database. In almost every case, this data must be validated to ensure that you don’t store useless, spurious, or contradictory information that might cause later problems.
Ideally, the validation of the user input should take place on the client side so that the user is immediately informed that there’s something wrong with the input before the form is posted back to the server. If this pattern is implemented correctly, it saves server resources and gives the user faster feedback. However, regardless of whether client-side validation is performed, the form’s data must also be validated on the server side. Otherwise, a shrewd attacker could hack the page by removing the client-side JavaScript that validates the input, saving the new page, and using it to submit bogus data.
Writing validation code by hand is a lengthy task, especially because the models for client-side programming (typically JavaScript) and server-side programming (in this case, ASP.NET) are quite different. The developers at Microsoft are well aware of this, so, in addition to the set of HTML and web controls, they also developed a set of validation controls. These controls can be declared on a web form and then bound to any other input control. Once bound to an input control, the validation control performs automatic client-side and server-side validation. If the corresponding control
C H A P T E R 4 ■ S E R V E R C O N T R O L S |
133 |
is empty, doesn’t contain the correct data type, or doesn’t adhere to the specified rules, the validator will prevent the page from being posted back altogether.
■Note ASP.NET 2.0 adds exactly three new validation features. There’s new support for placing input controls into validation groups, a new BaseValidator.SetFocusOnError property, and a new CustomValidator.Validate EmptyText property.
The Validation Controls
ASP.NET includes six validation controls. These controls all perform a good portion of the heavy lifting for you, thereby streamlining the validation process and saving you from having to write tedious code. Even better, the validation controls are flexible enough to work with the custom rules you define, which makes your code more reusable and modular. Table 4-15 briefly summarizes each validator.
Table 4-15. The Validation Controls
Validation Control |
Description |
<asp:RequiredFieldValidator> |
Checks that the control it has to validate is not empty when |
|
the form is submitted. |
<asp:RangeValidator> |
Checks that the value of the associated control is within |
|
a specified range. The value and the range can be |
|
numerical—a date or a string. |
<asp:CompareValidator> |
Checks that the value of the associated control matches a |
|
specified comparison (less than, greater than, and so on) |
|
against another constant value or control. |
<asp:RegularExpressionValidator> |
Checks if the value of the control it has to validate matches |
|
the specified regular expression. |
<asp:CustomValidator> |
Allows you to specify any client-side JavaScript validation |
|
routine and its server-side counterpart to perform your |
|
own custom validation logic. |
<asp:ValidationSummary> |
Shows a summary with the error messages for each failed |
|
validator on the page (or in a pop-up message box). |
|
|
It’s important to note that you can use more than one validator for the same control. For example, you could use a validator to ensure that an input control is not empty and another to ensure that it contains data of a certain type. In fact, if you use the RangeValidator, CompareValidator, or RegularExpressionValidator, validation will automatically succeed if the input control is empty, because there is no value to validate. If this isn’t the behavior you want, you should add a RequiredFieldValidator to the control. This ensures that two types of validation will be performed, effectively restricting blank values.
Although you can’t validate RadioButton or CheckBox controls, you can validate the TextBox (the most common choice) and other controls such as ListBox, DropDownList, RadioButtonList, HtmlInputText, HtmlTextArea, and HtmlSelect. When validating a list control, the property that is being validated is the Value property of the selected ListItem object. Remember, the Value property is a hidden attribute that stores a piece of information in the HTML page for each list item, but it isn’t displayed in the browser. If you don’t use the Value attribute, you can’t validate the control (validating the text of the selection isn’t a supported option).
134 C H A P T E R 4 ■ S E R V E R C O N T R O L S
Technically, every control class has the option of designating one property that can be validated using the ValidationProperty attribute. For example, if you create your own control class named FancyTextBox, here’s how you would designate the Text property as the property that supports validation:
[ValidationProperty("Text")]
public class FancyTextBox : WebControl {...}
You’ll learn more about how attributes work with custom controls in Chapter 28.
The Validation Process
You can use the validation controls to verify a page automatically when the user submits it or to verify it manually in your code. The first approach is the most common.
When using automatic validation, the user receives a normal page and begins to fill in the input controls. When finished, the user clicks a button to submit the page. Every button has a CausesValidation property, which can be set to true or false. What happens when the user clicks the button depends on the value of the CausesValidation property.
•If CausesValidation is false, ASP.NET will ignore the validation controls, the page will be posted back, and your event-handling code will run normally.
•If CausesValidation is true (the default), ASP.NET will automatically validate the page when the user clicks the button. It does this by performing the validation for each control on the page. If any control fails to validate, ASP.NET will return the page with some error information, depending on your settings. Your click event-handling code may or may not be executed—meaning you’ll have to specifically check in the event handler whether the
page is valid.
■Note Many other buttonlike controls that can be used to submit the page also provide the CausesValidation property. Examples include the LinkButton, ImageButton, and BulletedList.
Based on this description, you’ll realize that validation happens automatically when certain buttons are clicked. It doesn’t happen when the page is posted back because of a change event (such as choosing a new value in an AutoPostBack list) or if the user clicks a button that has CausesValidation set to false. However, you can still validate one or more controls manually and then make a decision in your code based on the results.
In browsers that support it, ASP.NET will automatically add code for client-side validation. In this case, when the user clicks a CausesValidation button, the same error messages will appear without the page needing to be submitted and returned from the server. This increases the responsiveness of the application. However, if the page validates successfully on the client side, ASP.NET will still revalidate it when it’s received at the server. By performing the validation at both ends, your application can be as responsive as possible but still remain secure.
■Note In ASP.NET 1.x, the validation controls emitted client-side JavaScript only for Internet Explorer browsers. Fortunately, ASP.NET 2.0 finally remedies the gap, with support for client-side scripts on Netscape and Firefox.
C H A P T E R 4 ■ S E R V E R C O N T R O L S |
135 |
Figure 4-12 shows a page that uses validation with several text boxes and ends with a validation summary. In the following section, you’ll learn about how you can use the different validators in this example.
Figure 4-12. Validating a sample page
The BaseValidator Class
The validation control classes are found in the System.Web.UI.WebControls namespace and inherit from the BaseValidator class. This class defines the basic functionality for a validation control. Table 4-16 describes its properties.
136C H A P T E R 4 ■ S E R V E R C O N T R O L S
Table 4-16. BaseValidator Members
Member |
Description |
ControlToValidate |
Indicates the input control to validate. |
Display |
Indicates how the error message will be shown. If Static, the space |
|
required to show the message will be calculated and added to the space |
|
layout in advance. If Dynamic, the page layout will dynamically change to |
|
show the error string. Be aware that although the dynamic style could |
|
seem useful, if your layout is heavily based on table structures, it could |
|
change quite a bit if multiple strings are dynamically added, and this could |
|
confuse the user. |
EnableClientScript |
A Boolean property that specifies whether the client-side validation will |
|
take place. It is true by default. |
Enabled |
A Boolean property that allows the user to enable or disable the validator. |
|
When the control is disabled, it does not validate anything. This property |
|
is usually used programmatically to change the enabled state according to |
|
the current page state or according to another application’s settings. |
ErrorMessage |
Error string that will be shown in the errors summary by the |
|
ValidationSummary control, if present. |
Text |
The error text that will be displayed in the validator control if the attached |
|
input control fails its validation. |
IsValid |
This property is also usually read or set only from script code (or the code- |
|
behind class) to determine whether the associated input control’s value is |
|
valid. This property can be checked on the server after a postback, but if |
|
the client-side validation is active and supported by the client browser, the |
|
execution won’t get to the server if the value isn’t valid. (In other words, |
|
you check this property just in case the client-side validation did not run.) |
|
Remember that you can also read the Page.IsValid property to know in a |
|
single step if all the input controls are in a valid state. Page.IsValid returns |
|
true only if all the contained controls are valid. |
SetFocusOnError |
If true, when the user attempts to submit a page that has an invalid |
|
control, the browser switches focus to the input control so the value can |
|
be easily corrected. (If false, the button or control that was clicked to post |
|
the page retains focus.) This feature works for both client-side and server- |
|
side validation. If you have multiple validators with SetFocusOnError set |
|
to true, and all the input controls are invalid, the first input control in the |
|
tab sequence gets focus. |
ValidationGroup |
Allows you to group multiple validators into a logical group so that |
|
validation can be performed distinctly without involving other groups. |
Validate() |
This method revalidates the control and updates the IsValid property |
|
accordingly. The web page calls this method when a page is posted back |
|
by a CausesValidation control. You can also call it programmatically (for |
|
example, if you programmatically set the content of an input control and |
|
you want to check its validity). |
|
|
In addition, the BaseValidator class has other properties such as BackColor, Font, ForeColor, and others that are inherited (and in some case overridden) from the base class Label (and the classes it inherits from, such as WebControl and Control). Every derived validator adds its own specific properties, which you’ll see in the following sections.
C H A P T E R 4 ■ S E R V E R C O N T R O L S |
137 |
The RequiredFieldValidator Control
The simplest available control is RequiredFieldValidator, whose only work is to ensure that the associated control is not empty. For example, the control will fail validation if a linked text box doesn’t contain any content (or just contains spaces). Alternatively, instead of checking for blank values you can specify a default value using the InitialValue property. In this case, validation fails if the content in the control matches this InitialValue (indicating that the user hasn’t changed it in any way).
Here is an example of a typical RequiredFieldValidator:
<asp:TextBox runat="server" ID="Name" /> <asp:RequiredFieldValidator runat="server"
ControlToValidate="Name" ErrorMessage="Name is required" Display="dynamic">*
</asp:RequiredFieldValidator>
The validator declared here will show an asterisk (*) character if the Name text box is empty. This error text appears when the user tries to submit the form by clicking a button that has CausesValidation set to true. It also occurs on the client side in Internet Explorer 5.0 or above
as soon as the user tabs to a new control, thanks to the client-side JavaScript.
If you want to place a specific message next to the validated control, you should replace * with an error message. (You don’t need to use the ErrorMessage property. The ErrorMessage is required only if you want to show the summary of all the errors on the page using the ValidationSummary control, which you’ll see later in this chapter.) Alternatively, for a nicer result, you could use an HTML <img> tag to use a picture (such as the common ! sign inside a yellow triangle) with a tooltip for the error message. You’ll see this approach later in this chapter as well.
The RangeValidator Control
The RangeValidator control verifies that an input value falls within a predetermined range. It has three specific properties: Type, MinimumValue, and MaximumValue. The last two define the range of valid values, while Type defines the type of the data that will be typed into the input control and validated. The available values are Currency, Date, Double, Integer, and String.
The following example checks that the date entered falls within August 5 and August 20 (encoded in the form mm/dd/yyyy, so if your web server uses different regional settings, you’ll have to change the date format):
<asp:TextBox runat="server" ID="DayOff" /> <asp:RangeValidator runat="server" Display="dynamic"
ControlToValidate="DayOff" Type="Date" ErrorMessage="Day Off is not within the valid interval" MinimumValue="08/05/2002" MaximumValue="08/20/2002">*
</asp:RangeValidator>
The CompareValidator Control
The CompareValidator control compares a value in one control with a fixed value or, more commonly, a value in another control. For example, this allows you to check that two text boxes have the same data or that a value in one text box doesn’t exceed a maximum value established in another.
Like the RangeValidator control, the CompareValidator provides a Type property that specifies the type of data you are comparing. It also exposes the ValueToCompare and ControlToCompare properties, which allow you to compare the value of the input control with a constant value or the value of another input control, respectively. You use only one of these two properties.