Selecting Values

Several ASP.NET server controls allow the user to select a value or values:

CheckBox

Allows selection of Boolean data

CheckBoxList

A group of CheckBox controls that can be dynamically created and bound to a data source

RadioButton

Allows only a single option to be selected from a group

RadioButtonList

A group of RadioButton controls that can be dynamically created and bound to a data source

ListBox

Allows selection of one or more items from a predefined list

DropDownList

Similar to a ListBox, but allows only a single selection and displays the list only once the user has clicked it

BulletedList

Formatted with bullets and can be simple text or a link

All of these controls derive from the WebControl class, as shown in Figure 3-8 in Chapter 3. The RadioButton derives further from the CheckBox class, and the list controls all derive from the abstract ListControl class. We consider each of these controls and their AJAX Control Toolkit extenders in detail in upcoming sections. Also included in this section are two standalone AJAX controls, the Slider and Rating controls, which also allow you to select a value.

CheckBox Control

A CheckBox control provides a means for a user to select Boolean data (i.e., Yes/No or True/False). If you have several checkboxes arranged together (not to be confused with a CheckBoxList, discussed next), you can select multiple options. No option is mutually exclusive of another.

The CheckBox and RadioButton controls implement the ICheckBoxControl interface. This interface provides for a single property called Checked, and a single event called CheckedChanged.

CheckBox behavior

To demonstrate the Checked property and CheckedChanged event with respect to a CheckBox control, add to the C4_BasicControls website a new web form called CheckBoxDemo.aspx. It uses one of three CheckBox controls to control the appearance of a Label control, as shown in Figure 4-11. Clicking any of the checkboxes in this example—Underline?, Overline?, or Strikeout?—imposes that font attribute on the text string in the Label control.

The markup for CheckBoxDemo.aspx is shown in Example 4-20.

CheckBoxDemo.aspx in action

Figure 4-11. CheckBoxDemo.aspx in action

Example 4-20. CheckBoxDemo.aspx

<%@ Page Language="C#" AutoEventWireup="true"
   CodeFile="CheckBoxDemo.aspx.cs" Inherits="CheckBoxDemo" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
   <title>Checkbox Demo</title>
</head>
<body>
   <form id="form1" runat="server">
   <div>
      <asp:CheckBox ID="chkUnderline" runat="server"
         Text="Underline?" AutoPostBack="true"
         oncheckedchanged="chkUnderline_CheckedChanged" />
      <asp:CheckBox ID="chkOverline" runat="server"
         Text="Overline?" AutoPostBack="true"
         oncheckedchanged="chkOverline_CheckedChanged" />
      <asp:CheckBox ID="chkStrikeout" runat="server"
         Text="Strikeout?" AutoPostBack="true"
         oncheckedchanged="chkStrikeout_CheckedChanged" />
      <br />
      <br />
      <asp:Label ID="lblTime" runat="server"
         oninit="lblTime_Init" />
   </div>
   </form>
</body>
</html>

Each ASP.NET server control in this example, the Label and the three CheckBox controls, has an event handler. The Init event for the Label is handled to set the common format and content (the current date and time) of the label every time the page is posted. The CheckBox controls have their default CheckedChanged event handled.

This event passes a standard EventArgs argument, which does not expose any properties.

All these event handler methods are contained in the code-behind file listed in Example 4-21.

Example 4-21. Event handlers in CheckBoxDemo.aspx.cs

using System;

public partial class CheckBoxDemo : System.Web.UI.Page
{
   protected void lblTime_Init(object sender, EventArgs e)
   {
      lblTime.Font.Name = "Verdana";
      lblTime.Font.Size = 20;
      lblTime.Font.Bold = true;
      lblTime.Font.Italic = true;
      lblTime.Text = DateTime.Now.ToString();
   }
   protected void chkUnderline_CheckedChanged
      (object sender, EventArgs e)
   {
      lblTime.Font.Underline = chkUnderline.Checked;
   }

   protected void chkOverline_CheckedChanged
      (object sender, EventArgs e)
   {
      lblTime.Font.Overline = chkOverline.Checked;
   }

   protected void chkStrikeout_CheckedChanged
      (object sender, EventArgs e)
   {
      lblTime.Font.Strikeout = chkStrikeout.Checked;
   }
}

When you run CheckBoxDemo.aspx, you’ll see that each time you check or uncheck a CheckBox, the page will post back, and the text displayed will refresh with the new time and will be underlined, overlined, or ruled through depending on the state of each CheckBox.

Like all controls derived from WebControl, CheckBox controls have an ID property. But as the sample code in Example 4-20 shows, several other properties are not inherited from WebControl. These are listed in Table 4-11. Some, such as AutoPostBack and Text, are common to several other controls. Checked and TextAlign, meanwhile, are specific to the CheckBox class. All are read/write. Table 4-12 lists the CheckBox events.

Table 4-11. CheckBox properties not inherited from WebControl

Name

Type

Values

Description

AutoPostBack

Boolean

true, false

Determines whether automatic postback to the server will occur if the user changes the contents of the control. If false (the default), postback to the server will not occur until the page is posted, either by a button or other postback control or by a control with AutoPostBack set to true.

Checked

Boolean

true, false

Indicates whether the CheckBox control is checked. Default is false.

Text

String

 

The text label associated with the CheckBox.

TextAlign

TextAlign

Left, Right

Dictates whether the text label is on the left or right of the CheckBox. Default is Right.

Table 4-12. CheckBox events

Name

Description

CheckedChanged

This event is raised when the Checked property is changed. This event will not immediately post back to the server unless AutoPostBack is set to true.

CheckBox extenders

The AJAX Control Toolkit contains two extender controls that specifically target CheckBox controls:

ToggleButtonExtender

Allows you to replace the checkbox graphic with your own custom graphics to indicate whether it has been checked or not

MutuallyExclusiveCheckBoxExtender

Allows you to specify a group of CheckBoxes from which only one can be selected at any time

To demonstrate how you can use these together, the next example extends CheckBoxDemo.aspx, replacing the Strikeout? checkbox with our own graphics and making the Underline? and Overline? checkboxes mutually exclusive. Figure 4-12 shows the net result.

Add to the C4_BasicControls website a new AJAX web form called CheckBoxDemoWithAJAX.aspx. Add the highlighted code from Example 4-20 to CheckBoxDemoWithAJAX.aspx under the ScriptManager control, and add all the event handler code highlighted in Example 4-21 to CheckBoxDemoWithAJAX.aspx.cs.

To use the ToggleButtonExtender, you’ll need to add to the website one graphic to represent an unchecked CheckBox and another to represent a checked CheckBox. If you have none on hand, try using ToggleButton_Checked.gif and ToggleButton_Unchecked.gif from the AJAX Control Toolkit sample website in the ToggleButton directory. With that done, drag a ToggleButtonExtender onto the page beneath the three CheckBoxes. It has five mandatory properties to set, as listed in Table 4-13.

CheckBoxDemoWithAJAX.aspx in action

Figure 4-12. CheckBoxDemoWithAJAX.aspx in action

Table 4-13. ToggleButtonExtender mandatory properties

Name

Type

Description

CheckedImageUrl

String

The location of the image representing a checked CheckBox

ImageHeight

Integer

The height of the image

ImageWidth

Integer

The width of the image

TargetControlId

String

The ID of the CheckBox control being extended

UncheckedImageUrl

String

The location of the image representing an unchecked CheckBox

The ToggleButtonExtender has several more optional properties, listed in Table 4-14, which cover such circumstances as what happens when the CheckBox is disabled and alternative text for each image.

Table 4-14. ToggleButtonExtender optional properties

Name

Type

Description

CheckedImageAlternateText

String

Alternative text for screen readers describing the image for CheckedImageUrl

DisabledCheckedImageUrl

String

The location of the image representing a checked CheckBox that has been disabled on-screen

DisabledUncheckedImageUrl

String

The location of the image representing an unchecked CheckBox that has been disabled on-screen

UncheckedImageAlternateText

String

Alternative text for screen readers describing the image for UncheckedImageUrl

Set the ToggleControlExtender properties as highlighted in Example 4-22 and run the page to see how images now take the place of the standard checkbox.

Example 4-22. CheckBoxDemoWithAJAX.aspx

<%@ Page Language="C#" AutoEventWireup="true"
   CodeFile="CheckBoxDemoWithAJAX.aspx.cs"
   Inherits="CheckBoxDemoWithAJAX" %>

<%@ Register Assembly="AjaxControlToolkit"
   Namespace="AjaxControlToolkit" TagPrefix="cc1" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
   <title>CheckBox Demo With AJAX</title>
   <script type="text/javascript">
      function pageLoad() {
      }
   </script>
</head>

<body>
   <form id="form1" runat="server">
   <div>
      <asp:ScriptManager ID="ScriptManager1" runat="server" />
      <asp:CheckBox ID="chkUnderline" runat="server"
         Text="Underline?" AutoPostBack="true"
         oncheckedchanged="chkUnderline_CheckedChanged" />
      <asp:CheckBox ID="chkOverline" runat="server"
         Text="Overline?" AutoPostBack="true"
         oncheckedchanged="chkOverline_CheckedChanged" />
      <asp:CheckBox ID="chkStrikeout" runat="server"
         Text="Strikeout?" AutoPostBack="true"
         oncheckedchanged="chkStrikeout_CheckedChanged" />

      <cc1:ToggleButtonExtender ID="ToggleButtonExtender1"
         runat="server" TargetControlID="chkStrikeout"
         CheckedImageUrl="ToggleButton_Checked.gif"
         CheckedImageAlternateText="Disable Strikeout"
         UncheckedImageUrl="togglebutton_unchecked.gif"
         UncheckedImageAlternateText="Enable Strikeout"
         ImageWidth="19" ImageHeight="19" />

      <cc1:MutuallyExclusiveCheckBoxExtender
         ID="MutuallyExclusiveCheckBoxExtender1" runat="server"
         targetControlId="chkUnderline" Key="Decoration" />
      <cc1:MutuallyExclusiveCheckBoxExtender
         ID="MutuallyExclusiveCheckBoxExtender2" runat="server"
         targetControlId="chkOverline" Key="Decoration" />

      <br />
      <br />
      <asp:Label ID="lblTime" runat="server" OnInit="lblTime_Init" />
   </div>
   </form>
</body>
</html>

Next, you need to make the chkOverline and chkUnderline boxes mutually exclusive using MutuallyExclusiveCheckBoxExtender (MECBE) controls. Drag an MECBE onto the page under the ToggleButtonExtender. Set its TargetControlID to chkUnderline. Now add a second MECBE to the page under the first. Set its TargetControlId to chkOverline. Make the two checkboxes mutually exclusive by giving both MECBEs the same Key value—it doesn’t actually matter what value you use as long as it isn’t the same as another Key group name on the page. In Example 4-22, it’s set to Decoration.

Now run the page. Note how you can’t add overlines and underlines to the label at the same time. Furthermore, if you do try to do so, the Label updates correctly when one box is checked, and the other is unselected automatically.

RadioButton Control

A RadioButton control is very similar to, and in fact is derived from, a CheckBox control. The essential difference between the two classes is that RadioButton controls are typically grouped using the GroupName property, and only one RadioButton in the group can be checked (i.e., its Checked property is true) at one time. Changing the Checked property of one RadioButton control in the group to true changes the Checked property of all other controls in the group to false. In addition, radio buttons typically display as round, as opposed to the square checkboxes.

Tip

If you compare and contrast a RadioButton with a CheckBox extended with an MECBE, you might not perceive any difference between the two. But consider the case where you have two groups of RadioButtons on a page and you need to ensure that a particular choice in one group precludes a selection in the other group while others do not. MECBEs can work across the RadioButton groups as required.

To demonstrate, add a new web form called RadioButtonDemo.aspx to your C4_BasicControls website. This page contains three RadioButton controls to set the font size of a label. Each radio button is part of the group grpSize and all are set to post back when selected. The markup for RadioButtonDemo.aspx is shown in Example 4-23.

Example 4-23. RadioButtonDemo.aspx

<%@ Page Language="C#" AutoEventWireup="true"
   CodeFile="RadioButtonDemo.aspx.cs" Inherits="RadioButtonDemo" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
   <title>RadioButton Demo</title>
</head>

<body>
   <form id="form1" runat="server">
   <div>
      <asp:RadioButton ID="rdoSize10" runat="server" Text="10pt"
         GroupName="grpSize" AutoPostBack="true"
         OnCheckedChanged="grpSize_CheckedChanged" />
      <asp:RadioButton ID="rdoSize14" runat="server" Text="14pt"
         GroupName="grpSize" AutoPostBack="true"
         OnCheckedChanged="grpSize_CheckedChanged" />
      <asp:RadioButton ID="rdoSize16" runat="server" Text="16pt"
         GroupName="grpSize" AutoPostBack="true"
         OnCheckedChanged="grpSize_CheckedChanged" />
      <br />
      <br />
      <asp:Label ID="lblTime" runat="server" OnInit="lblTime_Init" />
   </div>
   </form>
</body>
</html>

You can see in Example 4-23 that all three RadioButton controls name the same method, grpSize_CheckedChanged, to handle their CheckedChanged event. This method, plus another to set the text and initial font attributes for the Label control, is saved in the code-behind file for the page, RadioButtonDemo.aspx.cs, listed in Example 4-24.

Example 4-24. RadioButtonDemo.aspx.cs

using System;
using System.Web.UI;

public partial class RadioButtonDemo : Page
{
   protected void grpSize_CheckedChanged(object sender, EventArgs e)
   {
      if (rdoSize10.Checked)
         lblTime.Font.Size = 10;
      else if (rdoSize14.Checked)
         lblTime.Font.Size = 14;
      else
         lblTime.Font.Size = 16;
   }
   protected void lblTime_Init(object sender, EventArgs e)
   {
      lblTime.Font.Name = "Verdana";
      lblTime.Font.Size = 20;
      lblTime.Font.Bold = true;
      lblTime.Font.Italic = true;
      lblTime.Text = DateTime.Now.ToString();
   }
}

The result of running it is shown in Figure 4-13.

RadioButtonDemo.aspx in action

Figure 4-13. RadioButtonDemo.aspx in action

Note that the grpSize_CheckedChanged method uses an if…else block to change the text size depending on which button is selected, but there are several ways to achieve the same end here. For example, you could use a C# switch statement to make it easier to add additional radio buttons in the future:

protected void grpSize_CheckedChanged(object sender, EventArgs e)
{
   RadioButton rb = (RadioButton)sender;

   switch (rb.ID)
   {
      case "rdoSize10":
         lblTime.Font.Size = 10;
         break;
      case "rdoSize14":
         lblTime.Font.Size = 14;
         break;
      case "rdoSize16":
         lblTime.Font.Size = 16;
         break;
    }
}

You could even replace the switch statement in this example with a much shorter statement:

lblTime.Font.Size = new FontUnit(rb.Text);

However, this line works only because the Text property for the Checkbox controls has been set to values which are also valid as values for Font.Size.

Selecting from a List

ASP.NET provides five server controls for selecting single or multiple items from a list:

  • BulletedList

  • CheckBoxList

  • DropDownList

  • ListBox

  • RadioButtonList

All of these controls are derived from ListControl and have much in common:

  • The ListItem object (the object that encapsulates the information displayed by individual items in the list) works exactly the same way for all the ListControl objects, with a Value property and a Text property.

  • The Items property of the control contains the collection of all the ListItems.

  • ListItem objects can be added to the Items collection either statically, that is, declaratively in the content file, programmatically through the Add method, or from a data source.

    You can access the Data Source Configuration Wizard or the ListItem Collection Editor dialog box by clicking the control’s smart tag, the little icon in the upper-right corner of the control.

  • The SelectedIndex and SelectedItem properties of the control point to the selected item with the lowest index. For single-select controls, such as the DropDownList, the RadioButtonList, and the ListBox (if the SelectionMode property is set to ListSelectionMode.Single, the default value), the selected index is the lowest index by definition. For multiselect controls, such as CheckBoxList and the ListBox with the SelectionMode property set to ListSelectionMode.Multiple, these properties will refer to the selected item with the lowest index. To discover any other selected items, you’ll need to iterate through the control’s Items collection and test the Selected property of each ListItem therein.

  • The SelectedValue property of the control retrieves or specifies the value of the selected item.

  • The AppendDataBoundItems property of the control allows items added through data binding (described in Chapter 8) to be added to the Items collection, rather than replacing the Items collection, which is the default behavior. This is useful if you want to add a value statically—such as the text “(Select a value)”—and then add the remaining items by using data binding.

  • All five controls raise and respond to the SelectedIndexChanged event.

The ListBox and DropDownList controls differ from the other list controls (BulletedList, CheckBoxList, and RadioButtonList) in that they appear to the user to be a single control (a listbox or a drop-down list) rather than a collection of links, buttons, or checkboxes. The ListBox and DropDownList controls lend themselves to longer lists because they scroll.

Table 4-15 summarizes the differences among the five list controls.

Table 4-15. Differences among the five list controls

Characteristic

BulletedList

CheckBoxList

RadioButtonList

DropDownList

ListBox

Single selection only

x

 

x

x

 

Able to select more than one item

 

x

  

x

Displays the entire list by default

x

x

x

 

x (using a vertical scroll bar if necessary)

Displays a single item at a time, along with a button for seeing the entire list

   

x

 

Best for short lists

x

x

x

  

Best for long lists

   

x

x

The following sections describe the controls and objects related to selecting items from a list.

ListItem Object

As mentioned earlier, all five server controls are derived from the ListControl class. A ListControl control contains a collection of ListItem objects called Items. Each ListItem object has four read/write properties, detailed in Table 4-16.

Table 4-16. Properties of the ListItem object

Name

Type

Description

Enabled

Boolean

If set to false, makes an item invisible when the list is displayed, although it remains in the Items collection.

Selected

Boolean

A value indicating whether the item has been selected or not.

Text

String

The text string displayed for a ListItem.

Value

String

A value associated with a ListItem. The value is not displayed, but it is available programmatically.

When dealing with lists, displaying one thing to the user but passing something different to your code is common. For example, if you’re presenting your users with a list of states, the list might display state names, such as Massachusetts. But when your users select an item, the program will pass the selected item as MA. Massachusetts would be the ListItem object’s Text property, and MA would be the Value property. This comes in handy, for example, when translating the site into another language. In this case, you need only translate the contents of the Text property and leave the Value property alone:

<asp:ListItem value="air">By air</asp:ListItem>
<asp:ListItem value="air">Par avion</asp:ListItem>
<asp:ListItem value="air" text="Auf dem Luftweg" />

If only the Text property is set for a ListItem, the same value is also used for the Value property of the ListItem:

<asp:ListItem>Item 7</asp:ListItem>
<asp:ListItem text="Item 7"></asp:ListItem>
<asp:ListItem text="Item 7"/>

If both a Text property and inner HTML content are specified, the inner HTML content will be displayed. For example, consider the following line:

<asp:ListItem text="Item 7">Item 8</asp:ListItem>

If you used that line, “Item 8” would be displayed on the web page.

CheckBoxList Control

The CheckBoxList is a parent control containing a collection of CheckBox items. It is very similar to the group of CheckBox controls shown previously in CheckBoxDemo.aspx in Figure 4-11, except all the child checkboxes are handled as a group. The CheckBoxList control derives from ListControl rather than directly from WebControl.

The CheckBoxList control is better suited than individual checkboxes for creating a series of checkboxes out of data from a database, although either type of control can be bound to data. Chapter 8 discusses data binding.

There are three ways to add items to the Items collection of a CheckBoxList:

  • Declaratively using the <asp:ListItem> control element

  • Programmatically from an array or other collection

  • Dynamically from a data source such as a database

Adding items declaratively

To demonstrate how to add list items declaratively in the content file, add a new web form called CheckBoxList-DeclarativeItems.aspx to your C4_BasicControls website. You’ll also use some of the CheckBoxList control’s properties to set its appearance and behavior.

Drag a CheckBoxList control onto the page from the Toolbox and then, in Source view, add six list items as shown in Example 4-25.

Example 4-25. CheckBoxList-DeclarativeItems.aspx

<%@ Page Language="C#" AutoEventWireup="true" 
   CodeFile="CheckBoxList-DeclarativeItems.aspx.cs"
   Inherits="CheckBoxList_DeclarativeItems" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
   <title>CheckBoxList Demo - Declaring Items Individually</title>
</head>

<body>
   <form id="form1" runat="server">
   <div>
      <asp:CheckBoxList ID="cblItems" runat="server"
         RepeatDirection="Horizontal" RepeatColumns="2"
         RepeatLayout="Flow">
         <asp:ListItem>Item 1</asp:ListItem>
         <asp:ListItem>Item 2</asp:ListItem>
         <asp:ListItem>Item 3</asp:ListItem>
         <asp:ListItem>Item 4</asp:ListItem>
         <asp:ListItem>Item 5</asp:ListItem>
         <asp:ListItem>Item 6</asp:ListItem>
      </asp:CheckBoxList>
   </div>
   </form>
</body>
</html>

Because no events are handled in this page, and hence no event handlers, there are no additions to be made to the code-behind file, CheckBoxList-DeclarativeItems.aspx.cs. When you run the page, you’ll see that the six list items have been split alternately into two columns, as shown in Figure 4-14. This is because the list’s RepeatColumns property is set to 2 and the RepeatDirection property is set to Horizontal.

The CheckBoxList has a number of properties that determine how the items in the list are displayed on the page. These and other key read/write properties appear in Table 4-17.

CheckBoxList-DeclarativeItems.aspx in action

Figure 4-14. CheckBoxList-DeclarativeItems.aspx in action

Table 4-17. Properties of the CheckBoxList control

Name

Type

Values

Description

AutoPostBack

Boolean

true, false

Determines whether automatic postback to the server will occur if the user changes the contents of the control. If false, postback to the server will not occur until the page is posted, either by a button or by another control with AutoPostBack set to true. Its default value is false.

CellPadding

Integer

Integer

Distance in pixels between the border and contents of a cell. The default is -1, which indicates the property is not set.

CellSpacing

Integer

Integer

Distance in pixels between the border and contents of a cell. The default is -1, which indicates the property is not set.

DataSource

Object

 

Source that populates the control.

RepeatColumns

Integer

Integer

Number of columns to display.

RepeatDirection

 

Horizontal, Vertical

Horizontal specifies that items are loaded from left to right, and then top to bottom. Vertical specifies items are loaded top to bottom, and then left to right. Default is Vertical.

RepeatLayout

 

Flow, Table

Flow specifies items are displayed without a table structure. Table specifies that items are displayed in a table structure. Default is Table.

Selected

Boolean

true, false

Indicates that a list item has been selected. Default is false.

TextAlign

TextAlign

Left, Right

Dictates whether the text label is on the left or right of the checkboxes. Default is Right.

You can manually type the ListItem objects into the content file (IntelliSense will help minimize the typing), or you can use the Collection Editor. To use the Collection Editor, select the CheckBoxList in Design view, click the smart tag (the little icon in the upper-right corner of the control in Design view), and select Edit Items from the Smart Tag menu. The dialog box shown in Figure 4-15 will appear. Use this dialog box to add or remove ListItem objects and change their properties.

The ListItem Collection Editor

Figure 4-15. The ListItem Collection Editor

Adding items programmatically from an array or collection

Sometimes you do not know at design time what checkboxes you want to create. For example, you may want your program to populate the list depending on the value of other controls on the page. In these cases, you need to be able to add items to the Items collection programmatically.

To demonstrate, add a new web form called CheckBoxList-ArrayItems.aspx to your C4_BasicControls website. In this example, ListItem objects are added both declaratively, just like the previous example, and programmatically in the code-behind page. Indeed, the markup for CheckBoxList-ArrayItems.aspx is exactly the same as the previous example, with the single exception of a new line, highlighted in Example 4-26.

Example 4-26. CheckBoxList-ArrayItems.aspx

<%@ Page Language="C#" AutoEventWireup="true" 
   CodeFile="CheckBoxList-ArrayItems.aspx.cs"
   Inherits="CheckBoxList_ArrayItems" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
   <title>CheckBoxListDemo - Populating Items From An Array</title>
</head>
<body>
   <form id="form1" runat="server">
   <div>
      <asp:CheckBoxList ID="cblItems" runat="server" 
         RepeatDirection="Horizontal" RepeatColumns="2" 
         RepeatLayout="Flow"
         oninit="cblItems_Init">
         <asp:ListItem>Item 1</asp:ListItem>
         <asp:ListItem>Item 2</asp:ListItem>
         <asp:ListItem>Item 3</asp:ListItem>
         <asp:ListItem>Item 4</asp:ListItem>
         <asp:ListItem>Item 5</asp:ListItem>
         <asp:ListItem>Item 6</asp:ListItem>
      </asp:CheckBoxList>
   </div>
   </form>
</body>
</html>

This new line is the key to the page, assigning an event handler for the CheckBoxList control’s Init event which is implemented in the code-behind file, CheckBoxList-ArrayItems.aspx.cs, the highlighted code in Example 4-26. This method creates a string array of book categories to add to the list of checkboxes and then uses a foreach loop to iterate through the array to add them to the list. In each iteration of the loop, a new ListItem object is created and added to the Items collection of the CheckBoxList control. The code in full is highlighted in Example 4-27.

Example 4-27. The code-behind file, CheckBoxList-ArrayItems.aspx.cs

using System;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class CheckBoxList_ArrayItems : Page
{
   protected void cblItems_Init(object sender, EventArgs e)
   {
      // create an array of items to add
      string[] Categories =
         { "SciFi", "Fiction", "Computers", "History", "Religion" };
      foreach (string category in Categories)
      {
         cblItems.Items.Add(new ListItem(category));
      }
   }
}

When you run the page, you’ll see that the list items added programmatically come after those added declaratively, as shown in Figure 4-16.

CheckBoxList-ArrayItems.aspx in action

Figure 4-16. CheckBoxList-ArrayItems.aspx in action

You can modify the code in Examples Example 4-26 and Example 4-27 to add Value properties for some of the ListItems created in the CheckBoxList declaration, as well as in all the ListItem objects created in the cblItems_Init event procedure. This is demonstrated in CheckBoxList-ArrayItemsAndValues.aspx, copied from CheckBoxList-ArrayItems.aspx and modified. The resultant web page is shown in Figure 4-17.

CheckBoxList-ArrayItemsAndValues.aspx in action

Figure 4-17. CheckBoxList-ArrayItemsAndValues.aspx in action

The markup for CheckBoxList-ArrayItemsAndValues.aspx is listed in Example 4-28; the highlighted lines of code are the ones that differ from Example 4-26.

Example 4-28. CheckBoxList-ArrayItemsAndValues.aspx

<%@ Page Language="C#" AutoEventWireup="true"
   CodeFile="CheckBoxList-ArrayItemsAndValues.aspx.cs"
   Inherits="CheckBoxList_ArrayItemsAndValues" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
   <title>
      CheckBoxListDemo - Populating Items and Values From An Array
   </title>
</head>

<body>
   <form id="form1" runat="server">
   <div>
      <asp:CheckBoxList ID="cblItems" runat="server" 
         RepeatDirection="Horizontal" RepeatColumns="2" 
         RepeatLayout="Flow"
         oninit="cblItems_Init">
         <asp:ListItem Value="1">Item 1</asp:ListItem>
         <asp:ListItem Value="2" Text="Item 2" />
         <asp:ListItem Text="Item 3" />
         <asp:ListItem Text="Item 4">Inner Item 4</asp:ListItem>
         <asp:ListItem Value="5"></asp:ListItem>
         <asp:ListItem>Item 6</asp:ListItem>
      </asp:CheckBoxList>
   </div>
   </form>
</body>
</html>

The changes to the cblItems_Init event handler from Example 4-27 are highlighted in Example 4-29.

Example 4-29. The code-behind file, CheckBoxList-ArrayItemsAndValues.aspx.cs

using System;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class CheckBoxList_ArrayItemsAndValues : Page
{
   protected void cblItems_Init(object sender, EventArgs e)
   {
      // create an array of items to add
      string[] Categories = 
         { "SciFi", "Fiction", "Computers", "History", "Religion" };
      string[] Code =
         { "sf", "nvl", "cmp", "his", "rel" };

      for (int i=0; i<Categories.Length; i++)
      {
         cblItems.Items.Add(new ListItem(Categories[i], Code[i]));
      }
   }
}

In cblItems_Init, listed in Example 4-27, where you previously created a single string array to hold the Text properties, there are now two string arrays: one for the Text properties and one for the Value properties. You now use the overloaded Add method, passing in a single argument consisting of a ListItem object and a for loop rather than a foreach loop to iterate through both arrays in a single iteration.

Tip

An object may overload its methods, which means it may declare two or more methods with the same name. The compiler differentiates among these methods based on the number and type of parameters provided.

For example, the ListItemCollection class overloads the Add method. One version takes a string, and the other version takes a ListItem object.

Finally, in creating the static ListItems, you used several different methods of creating Values and Text, including instances of missing Text (Item 5), missing Values (Item 3, Item 4, Item 6), and a divergent Text property from inner HTML content (Item 4). The differences between Figures Figure 4-16 and Figure 4-17 can be seen in Items 4 and 5.

You can see that if the Value is missing, the Text is displayed. If the Text is missing, the Value will be displayed. If the Text is different from the inner HTML content, the inner HTML content will be displayed.

Adding items from a data source

The real power of adding items programmatically comes when you can use a data source to populate the items in a CheckBoxList control. The ultimate data source, obviously, is a database. We will cover how to bind information from a database into your controls in Chapters Chapter 7 through Chapter 10. However, you can use the array we just created to demonstrate binding to a data source.

Add to your C4_BasicControls website a new page called CheckBoxList-ArrayItemsDataBind.aspx, and copy the code for the previous example to it. Modify only the cblItems_Init event handler method in the code-behind file. Replacing the for loop and second array in cblItems_Init in Example 4-27 with two lines of code (which specify the data source and then bind to it), the method now appears as shown in Example 4-30.

Example 4-30. The code-behind file, CheckBoxList-ArrayItemsDataBind.aspx.cs

using System;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class CheckBoxList_ArrayItemsDataBind : Page
{
   protected void cblItems_Init(object sender, EventArgs e)
   {
      // create an array of items to add
      string[] Categories = 
         { "SciFi", "Novels", "Computers", "History", "Religion" };
      cblItems.DataSource = Categories;
      cblItems.DataBind();
   }
}

You might expect the results to be unchanged from Figure 4-17, but that is not the case. Instead, you get the results shown in Figure 4-18.

Unexpected results produced by data binding

Figure 4-18. Unexpected results produced by data binding

In the previous example, using the for loop, ListItems were added by the Init method after the control was created. In this example, the preexisting ListItem objects were replaced by the new data source because the ListControl.Items collection is initialized by the data source, so any previously defined ListItem objects are lost.

That is the default behavior when data binding to a ListControl object. However, you can set the AppendDataBoundItems property of the control to true, in which case the data-bound items will be added to the existing Items collection, rather than replacing the existing Items collection.

Responding to user selections

When a user checks or unchecks one of the checkboxes in a CheckBoxList, the SelectedIndexChanged event is raised. This event passes an argument of type EventArgs, which does not expose any properties. By handling this event, you can respond to the user selection on one of the checkboxes. As with most ASP.NET server controls, if AutoPostBack is set to true the response occurs immediately. Otherwise, the response occurs the next time the form is posted to the server.

To see this, copy the previous example to a new page, CheckBoxList-RespondingToEvents.aspx, and then add the highlighted code from the content file in Example 4-31.

Example 4-31. CheckBoxList-RespondingToEvents.aspx

<%@ Page Language="C#" AutoEventWireup="true" 
   CodeFile="CheckBoxList-RespondingToEvents.aspx.cs"
   Inherits="CheckBoxList_RespondingToEvents" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>CheckBoxList - Responding To Events</title>
</head>

<body>
    <form id="form1" runat="server">
    <div>
      <asp:CheckBoxList ID="cblItems" runat="server" 
         oninit="cblItems_Init" AutoPostBack="true"
         OnSelectedIndexChanged="cblItems_SelectedIndexChanged">
         <asp:ListItem>Item 1</asp:ListItem>
         <asp:ListItem>Item 2</asp:ListItem>
         <asp:ListItem>Item 3</asp:ListItem>
         <asp:ListItem>Item 4</asp:ListItem>
         <asp:ListItem>Item 5</asp:ListItem>
         <asp:ListItem>Item 6</asp:ListItem>
      </asp:CheckBoxList>
       <asp:Label ID="lblCategory" runat="server"></asp:Label>
    </div>
    </form>
</body>
</html>

You’ll also need to add a new method to handle the event in the code-behind file, CheckBoxList-RespondingToEvents.aspx.cs, as highlighted in Example 4-32. This method checks to see whether any items are selected. If no items are selected, the method sets the Label control with an appropriate message. If at least one item is selected, the method iterates over all the items in the CheckBoxList and builds up a string indicating which items are checked, to be displayed by the Label.

Example 4-32. CheckBoxList-RespondingToEvents.aspx.cs

using System;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class CheckBoxList_RespondingToEvents : Page
{
   protected void cblItems_Init(object sender, EventArgs e)
   {
      // create an array of items to add
      string[] Genre = 
         { "SciFi", "Fiction", "Computers", "History", "Religion" };
      cblItems.DataSource = Genre;
      cblItems.DataBind();
   }

   protected void cblItems_SelectedIndexChanged
      (object sender, EventArgs e)
   {
      if (cblItems.SelectedItem == null)
      {
         lblCategory.Text = "<br />No genres selected.";
      }
      else
      {
         StringBuilder sb = new StringBuilder();

         foreach (ListItem li in cblItems.Items)
         {
            if (li.Selected)
            {
               sb.Append("<br/>" + li.Value + " - " + li.Text);
            }
         }
         lblCategory.Text = sb.ToString();
     }
   }
}

When you run this page you’ll see how it responds to your selecting and deselecting checkboxes in the list, as shown in Figure 4-19.

Note that you used the StringBuilder class in cblGenre_SelectedIndexChanged to create the string, rather than concatenating each string value onto the previous value, as in this line of C# code:

str += "<br/>" + li.Value + " - " + li.Text;
CheckBoxList_RespondingToEvents.aspx in action

Figure 4-19. CheckBoxList_RespondingToEvents.aspx in action

This is the preferred approach to building up a string because when you write the following code, it only appears as though you are concatenating the second part of the string onto firstString:

String firstString = "Hello";
firstString += " world";

What is actually happening, however, is that a second string is being allocated and assigned to your string reference, and the first string is being destroyed. If you do this a lot (e.g., in a tight loop), it is very inefficient because creating and destroying the string objects are time-consuming operations. The StringBuilder class provides a more efficient way of constructing strings, because it does not require that a new string be created with every modification. Once the string has been constructed in the StringBuilder, you then call its ToString() method to retrieve it, as we demonstrated in Example 4-32:

lblCategory.Text = sb.ToString();

RadioButtonList Control

The RadioButtonList control is very similar to the CheckBoxList control. Both are derived from the ListControl class and share all of the same properties, events, and methods. The only difference between the two (aside from the round versus square shape) is that the RadioButtonList control can have only one item selected at a time. When an item is selected, any other selected item is deselected.

The RadioButtonList and the CheckBoxList controls share two properties inherited from ListControl, shown in Table 4-18.

Table 4-18. Selection properties inherited from the ListControl class

Name

Type

Description

SelectedIndex

Integer

The lowest index of the selected items in the list. If equal to -1, nothing was selected.

SelectedItem

ListItem

The selected item with the lowest index. This property is read-only.

To demonstrate how these properties are useful, copy the contents of RadioButtonDemo.aspx to a new web page, called RadioButtonListDemo.aspx, in the C4_BasicControls website. Also copy the contents of the RadioButtonDemo.aspx.cs code-behind file to RadioButtonListDemo.aspx.cs. Replace the three radio buttons controlling the font size with a single RadioButtonList, calling it rblSize, as highlighted in Example 4-33.

Example 4-33. RadioButtonListDemo.aspx

<%@ Page Language="C#" AutoEventWireup="true" 
   CodeFile="RadioButtonListDemo.aspx.cs"
   Inherits="RadioButtonListDemo" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
   <title>RadioButtonList Demo</title>
</head>

<body>
   <form id="form1" runat="server">
   <div>
      <asp:RadioButtonList ID="rblSize" runat="server"
         AutoPostBack="true"
         onselectedindexchanged="rblSize_SelectedIndexChanged">
         <asp:ListItem Text="10pt" Value="10" />
         <asp:ListItem Text="14pt" Value="14" />
         <asp:ListItem Text="16pt" Value="16" />
      </asp:RadioButtonList>
      <br />
      <br />
      <asp:Label ID="lblTime" runat="server" OnInit="lblTime_Init" />
   </div>
   </form>
</body>
</html>

The code-behind file for this page also needs a few changes, as highlighted in Example 4-34. Instead of a handler for the CheckedChanged event of each individual RadioButton, you now need a handler for the SelectedIndexChanged event of the RadioButtonList. When this event is raised and the page posts back to the server, the method checks the RadioButtonList control’s SelectedIndex property to see whether any of the items in the list have been selected and then uses the Value of that item to set the font size of the text in the Label. If no item has been selected, the SelectedIndex property is equal to -1. If an item has been selected, SelectedIndex will be greater than -1.

Example 4-34. RadioButtonListDemo.aspx.cs

using System;
using System.Web.UI;

public partial class RadioButtonListDemo : Page
{
   protected void lblTime_Init(object sender, EventArgs e)
   {
      lblTime.Font.Name = "Verdana";
      lblTime.Font.Size = 20;
      lblTime.Font.Bold = true;
      lblTime.Font.Italic = true;
      lblTime.Text = DateTime.Now.ToString();
   }

   protected void rblSize_SelectedIndexChanged
      (object sender, EventArgs e)
   {
      //  Check to verify that something has been selected.
      if (rblSize.SelectedIndex > -1)
      {
         int size = Convert.ToInt32(rblSize.SelectedItem.Value);
         lblTime.Font.Size = size;
      }
   }
}

Note that we could have written the last two highlighted lines of code in the preceding snippet as a single line, as follows:

lblTime.Font.Size = Convert.ToInt32(rblSize.SelectedItem.Value);

However, the more verbose version used in the example makes the code easier to read and debug, and that’s always a preferable thing.

The final page is shown in Figure 4-20 after selecting a font size.

When you run the page, you’ll see that a RadioButtonList looks similar to the individual radio buttons used earlier in the chapter, but it is much easier to work with programmatically as demonstrated even in this simple example. Rather than a cumbersome if or switch statement, you can use the control’s SelectedItem and SelectedIndex properties; a much quicker and more readable solution.

The SelectedIndex property represents the lowest integer value index of all the selected items. The SelectedItem property returns the ListItem object in the list pointed to by SelectedIndex. From the ListItem object, you can then retrieve its text and value, select or deselect it, and change any of its HTML attributes.

RadioButtonListDemo.aspx in action

Figure 4-20. RadioButtonListDemo.aspx in action

Because a RadioButtonList, by definition, can have at most a single selected item, SelectedIndex and SelectedItem will tell you which item is selected. When you apply it to a CheckBoxList control or other multiselect ListControl control, however, you must remember that SelectedIndex and SelectedItem return only the first selected item in the list. To find out whether there are more, you must iterate through the list’s Items collection, as shown in Example 4-34, and check each ListItem’s Selected property to see whether it is set to true.

DropDownList Control

DropDownList controls display a single item at a time with a button for displaying the list. Only a single item can be selected.

DropDownList behavior

To demonstrate a DropDownList, add to the C4_BasicControls website a new web form called DropDownListDemo.aspx, and drag a DropDownList control and a Label onto it from the Toolbox. The aim of the page will be to have the item selected in the DropDownList reflected in the Label’s text, as shown in Figure 4-21.

To ensure the DropDownList posts back to the server and updates the Label, its AutoPostBack property is set to true and its SelectedIndexChanged event is bound to a method in the code-behind file. Example 4-35 shows the markup for the page.

DropDownListDemo.aspx in action

Figure 4-21. DropDownListDemo.aspx in action

Example 4-35. DropDownListDemo.aspx

<%@ Page Language="C#" AutoEventWireup="true"
   CodeFile="DropDownListDemo.aspx.cs" Inherits="DropDownListDemo" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
   <title>DropDownList Demo</title>
</head>

<body>
   <form id="form1" runat="server">
   <div>
      <asp:DropDownList ID="ddlBooks" runat="server" 
         AutoPostBack="true" 
         OnSelectedIndexChanged="ddlBooks_SelectedIndexChanged" />
      <br />
      <br />
      <asp:Label ID="lblBookInfo" runat="server"></asp:Label>
   </div>
   </form>
</body>
</html>

The code-behind file, DropDownListDemo.aspx.cs, contains handlers for two events, as shown in Example 4-36. In the Page_Load method, items are added to the list in two steps. First, a two-dimensional string array is created to hold the Text and Value properties for the items. Then, the code loops through the items in the array adding a ListItem object to the list’s Items collection.

The second method, ddlBooks_SelectedIndexChanged, fires once a new item has been selected in the DropDownList and the page has posted back. It makes sure an item has been selected by testing to see whether its SelectedItem property is not -1 and then sets the Label control’s Text property to reflect the selected item’s Text and Value properties.

Example 4-36. DropDownListDemo.aspx.cs

using System;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class DropDownListDemo : Page
{
   protected void Page_Load(object sender, EventArgs e)
   {
      if (!IsPostBack)
      {
         //  Build 2 dimensional array for the lists       
         //  First dimension contains bookname       
         //  2nd dimension contains ISBN number       
         string[,] books = { 
            {"Learning ASP.NET 2.0 with AJAX", "9780596513976"},
            {"Beginning ASP.NET 2.0 with C#", "9780470042583"}, 
            {"Programming C#","9780596527433"}, 
            {"Programming .NET 3.5","978059652756X"}, 
            {"Programming .NET Windows Applications","0596003218"}, 
            {"Programming ASP.NET 3e","0596001711"},  
            {"WebClasses From Scratch","0789721260"}, 
            {"Teach Yourself C++ in 21 Days","067232072X"}, 
            {"Teach Yourself C++ in 10 Minutes","067231603X"},  
            {"XML & Java From Scratch","0789724766"}, 
            {"XML Web Documents From Scratch","0789723166"}, 
            {"Clouds To Code","1861000952"}, 
            {"C++ Unleashed","0672312395"} 
        };

         //  Now populate the list.       
         for (int i = 0; i < books.GetLength(0); i++)
         {
            //  Add both Text and Value 
            ddlBooks.Items.Add(new ListItem(books[i, 0], books[i, 1]));
         }
      }
   }

   protected void ddlBooks_SelectedIndexChanged
      (object sender, EventArgs e)
   {
      //  Check to verify that something has been selected.
      if (ddlBooks.SelectedIndex != -1)
      {
         lblBookInfo.Text = ddlBooks.SelectedItem.Text + 
            " --->ISBN: " + ddlBooks.SelectedValue;
      }
   }
}

The Page_Load method runs every time the page is reloaded, but it’s often not a good idea to have all the code it contains be executed each time the method is run. For instance, in many applications, the contents of lists and other controls are filled from a database, which can be an expensive operation. Hitting the database only when necessary makes the implementation more efficient. It also means that any selections made from a list are carried over postbacks. They would otherwise be lost when a list is rebound to a database or other data source.

The approach most often taken is to have this database access occur only when the page is first loaded, and for this purpose you test to see whether the IsPostBack property is true. The IsPostBack property is false when the page is first loaded, but it is set to true whenever the form is posted back to the server as a result of user action on one of the controls.

DropDownList extenders

The AJAX Control Toolkit contains two extender controls that target the DropDownList control. Both aim to make the selection of items from the list a little bit easier.

CascadingDropDown

In a situation where you have several related DropDownLists on the same page, updates the items in one list based on the choices made in other lists

ListSearchExtender

Helps the user work through very long (and unsorted) lists more quickly by allowing the user to start typing out the choice he wants from the list and highlighting the first option from the list that matches what he has typed

The CascadingDropDown extender control uses a web service (see Chapter 16) in the background to do the hard work, so this section will look solely at using the ListSearchExtender.

To demonstrate, you’ll add the ListSearchExtender to a copy of DropDownList.aspx to make it easier to search through the list to find the book you want to select. Figure 4-22 shows this in action.

The ListSearchExtender in action

Figure 4-22. The ListSearchExtender in action

Add a new AJAX web form to the C4_BasicControls website and call it DropDownListDemoWithAJAX.aspx. Copy the DropDownList and Label controls from DropDownListDemo.aspx to the new page underneath the ScriptManager control. Similarly, copy Page_Load and ddlBooks_SelectedIndexChanged from DropDownListDemo.aspx.cs to DropDownListDemoWithAJAX.aspx.cs.

Now drag a ListSearchExtender onto the page under the DropDownList. Set its TargetControlID property to ddlBooks and run the page. Observe that when the DropDownList is in focus, typing the first few letters of a book in the list puts the focus straight on the book in the list. Now, this behavior is true of an unextended DropDownList too, but the ListSearchExtender allows you to see what you’ve typed on top of the list as well, which a DropDownList by itself would not allow you to do.

Now tidy up the UI of the ListSearchExtender a bit more with PromptText, PromptPosition, and PromptCssClass. If you use this last property, you’ll also need to add the relevant CSS styles to your stylesheet. Example 4-37 shows the markup for DropDownListWithAJAX.aspx with the differences between it and DropDownList.aspx highlighted. There’s no change to the code-behind file.

Example 4-37. DropDownListDemoWithAJAX.aspx

<%@ Page Language="C#" AutoEventWireup="true"
   CodeFile="DropDownListDemoWithAJAX.aspx.cs"
   Inherits="DropDownListDemoWithAJAX" %>

<%@ Register Assembly="AjaxControlToolkit" TagPrefix="cc1"
   Namespace="AjaxControlToolkit" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
   <title>DropDownList Demo with AJAX</title>

   <script type="text/javascript">

      function pageLoad() {
      }

   </script>
   <style type="text/css">
      .PromptStyle {
      color: Red;
      font-style:italic;
      }
   </style>
</head>

<body>
   <form id="form1" runat="server">
   <div>
      <asp:ScriptManager ID="ScriptManager1" runat="server" />
      <asp:DropDownList ID="ddlBooks" runat="server" 
         AutoPostBack="true" 
         OnSelectedIndexChanged="ddlBooks_SelectedIndexChanged" />

      <cc1:ListSearchExtender ID="ListSearchExtender1" runat="server"
         TargetControlID="ddlBooks" PromptPosition="Top"
         PromptText="Type name of book to find it more quickly"
         PromptCssClass="PromptStyle" />
      <br />
      <br />
      <asp:Label ID="lblBookInfo" runat="server"></asp:Label>
   </div>
   </form>
</body>
</html>

The ListSearchExtender can also target a ListBox control.

ListBox Control

ListBox controls are very similar to DropDownList controls, except that multiple list items are visible on the screen by default (with the aid of a vertical scroll bar if necessary), and multiple items can be selected from it at once (by changing the SelectionMode property from the default value of Single to Multiple).

To demonstrate, add a new web form called ListBoxDemo.aspx to the C4_BasicControls website, and then add two ListBox controls to the form from the Toolbox. One will allow only single-item selection and the other will allow multiple-item selection, as shown in Example 4-38.

The first ListBox, with an ID of lbxSingle, is a single-selection listbox. The Rows property has been set to 6, and six items are displayed. Because the control has been populated with more than six items, a vertical scroll bar automatically appears. If a new item is selected, the first item is deselected. As with most of the examples in this chapter, AutoPostBack has been set to true so that the effects of the change are visible immediately.

The second ListBox control, with an ID of lbxMulti, is a multiple-selection listbox with its SelectionMode property set to Multiple. The Rows property has not been set, so the default four rows are visible. Because it is a multiselect listbox, the standard Windows techniques of multiselection can be used.

Example 4-38. ListBoxDemo.aspx

<%@ Page Language="C#" AutoEventWireup="true"
   CodeFile="ListBoxDemo.aspx.cs" Inherits="ListBoxDemo" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
   <title>ListBox Demo</title>
</head>
<body>
   <form id="form1" runat="server">
   <div>
      <h2>Single Selection</h2>
      <asp:ListBox ID="lbxSingle" runat="server"
         AutoPostBack="true" Rows="6"
         onselectedindexchanged="lbxSingle_SelectedIndexChanged" />
      <br />
      <br />
      <asp:Label ID="lblSingle" runat="server"></asp:Label>

      <h2>Multiple Selection</h2>
      <asp:ListBox ID="lbxMulti" runat="server" AutoPostBack="true"
         SelectionMode="Multiple"
         onselectedindexchanged="lbxMulti_SelectedIndexChanged" />
      <br />
      <br />
      <asp:Label ID="lblMulti" runat="server"></asp:Label>
   </div>
   </form>
</body>
</html>

The code-behind file, ListBoxDemo.aspx, is shown in Example 4-39. Both ListBox controls are populated from the same array when the page is initially loaded, but the techniques used to identify the selected item(s) in each ListBox are different, illustrating again the different uses of the SelectedItem and SelectedIndex properties.

The event handler for the single-selection listbox is similar to the one for the DropDownList or any other single-select ListControl, such as the RadioButtonList.

The event handler for the multiselect listbox shows two different techniques for building up the string of selected items. The first technique is like that used for the CheckBoxList. It first checks to see whether any items in the list are selected, and if so, it iterates through the collection of ListItem objects, checking each to see whether the Selected property is true. If the item is selected, the Text and Value properties will be added to the StringBuilder for output to a label.

The second technique, commented out in Example 4-39, uses the ListBox control’s GetSelectedIndices method to return an integer array of indexes of all the selected items. That array is iterated, with each selected ListItem being instantiated to get its Text and Value properties.

Example 4-39. ListBoxDemo.aspx.cs

using System;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class ListBoxDemo : Page
{
   protected void Page_Load(object sender, EventArgs e)
   {
      if (!IsPostBack)
      {
         //  Build 2 dimensional array for the lists
         //  First dimension contains bookname
         //  2nd dimension contains ISBN number
         string[,] books = {
            {"Learning ASP.NET 2.0 with AJAX", "9780596513976"},
            {"Beginning ASP.NET 2.0 with C#", "9780470042583"},
            {"Programming C#","9780596527433"},
            {"Programming .NET 3.5","978059652756X"},
            {"Programming .NET Windows Applications","0596003218"},
            {"Programming ASP.NET 3e","0596001711"},
            {"WebClasses From Scratch","0789721260"},
            {"Teach Yourself C++ in 21 Days","067232072X"},
            {"Teach Yourself C++ in 10 Minutes","067231603X"},
            {"XML & Java From Scratch","0789724766"},
            {"XML Web Documents From Scratch","0789723166"},
            {"Clouds To Code","1861000952"},
            {"C++ Unleashed","0672312395"}
        };

         //  Now populate the list. 
         for (int i = 0; i < books.GetLength(0); i++)
         {
            //  Add both Text and Value 
            lbxSingle.Items.Add(new ListItem(books[i, 0], books[i, 1]));
            lbxMulti.Items.Add(new ListItem(books[i, 0], books[i, 1]));
         }
      }
   }

   protected void lbxSingle_SelectedIndexChanged
      (object sender, EventArgs e)
   {
      //  Check to verify that something has been selected.
      if (lbxSingle.SelectedIndex > -1)
      {
         lblSingle.Text = lbxSingle.SelectedItem.Text +
            " ---> ISBN: " + lbxSingle.SelectedValue;
      }
   }

   protected void lbxMulti_SelectedIndexChanged(object sender, EventArgs e)
   {
      if (lbxMulti.SelectedItem == null)
      {
         lblMulti.Text = "No books selected.";
      }
      else
      {
         StringBuilder sb = new StringBuilder();

         foreach (ListItem li in lbxMulti.Items)
         {
            if (li.Selected)
            {
               sb.AppendFormat("<br/>{0} ---> ISBN: {1}", li.Text, li.Value);
            }
         }
         lblMulti.Text = sb.ToString();
      }
      //  Alternative technique
      //  foreach (int i in lbxMulti.GetSelectedIndices())
      //  {
      //     ListItem li = lbxMulti.Items[i];
      //     sb.AppendFormat("<br/>{0} ---> ISBN: {1}", li.Text, li.Value);
      //  }
      //  lblMulti.Text = sb.ToString();
   }
}

When you run the page and make a few selections, it should look like Figure 4-23.

ListBoxDemo.aspx in action

Figure 4-23. ListBoxDemo.aspx in action

ListBox controls have two read/write properties in addition to those inherited from ListControl. These properties are shown in Table 4-19.

Table 4-19. ListBox properties not inherited from ListControl

Name

Type

Values

Description

SelectionMode

ListSelectionMode

Single, Multiple

Determines whether a ListBox is in single-selection mode or multiple-selection mode. Default is Single.

Rows

Integer

 

Number of rows displayed. Default is four.

BulletedList Control

The BulletedList control provides an ASP.NET server control analog to the HTML ordered (<ol>) and unordered (<ul>) lists. The appearance and functionality of the list are controlled with properties of the BulletedList control. Like the other controls derived from ListControl, the BulletedList has an Items property, which is a collection of ListItem objects.

The style of the bullet is specified with the BulletStyle property. The valid values are contained within the BulletStyle enumeration, with values such as Circle, Disc, Numbered, LowerAlpha, UpperAlpha, LowerRoman, and UpperRoman. If the BulletStyle property is not set, a value of NotSet is the default, in which case the browser determines what style of bullet to use, typically the same as Disc, although this may vary by browser.

If the BulletStyle property is set to a numeric or alphabetic style, such as Numbered, LowerAlpha, UpperAlpha, LowerRoman, or UpperRoman, the starting value can be set using the FirstBulletNumber property. The default value is 1. Numeric bullet styles (Numbered, LowerRoman, UpperRoman) display numbers, and alphabetic types display the alphabetical equivalent.

The DisplayMode property determines appearance and functionality. It can be any one of the three values of the BulletedListDisplayMode enumeration:

Text

The default value; this causes the list content to display as text. No events will be associated with the control if this value is used, that is, there is no user interaction with this control.

HyperLink

Each ListItem is displayed as an underlined link. When an item is clicked, no server-side events are raised, and the form is not posted back to the server. Rather, like the HyperLink control itself, the user is navigated directly to the URL specified in the Value property of the ListItem that was clicked.

The Target property of the BulletedList control works in conjunction with the DisplayMode set to HyperLink, dictating the browser window in which the target page will be displayed. The values of the Target property are the same as those listed in Table 4-5 for the HyperLink control.

LinkButton

Each ListItem is displayed as an underlined link, exactly like the HyperLink. However, when the user clicks an item, the BulletedList.Click event is raised and the page is immediately posted back to the server. A server-side event handler, specified by the OnClick attribute of the BulletedList control, is executed.

BulletedList behavior

The example shown in Figure 4-24, BulletedListDemo.aspx, demonstrates the different bullet styles, starting numbers, and display modes, as well as event handling with the BulletedList control. The content file for the example is shown in Example 4-40, and the event handler methods from the code-behind file are shown in Example 4-41.

BulletedListDemo.aspx in action

Figure 4-24. BulletedListDemo.aspx in action

Example 4-40. BulletedListDemo.aspx

<%@ Page Language="C#" AutoEventWireup="true"
   CodeFile="BulletedListDemo.aspx.cs" Inherits="BulletedListDemo" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
   <title>BulletedList Demo</title>
</head>

<body>
   <form id="form1" runat="server">
   <div>
      <asp:BulletedList ID="bltBooks" runat="server" 
         Target="_blank" onclick="bltBooks_Click" />
      <table>
         <tr>
            <td colspan="3" id="tdMessage" runat="server"></td>
         </tr>
         <tr>
            <td><em>BulletStyle</em></td>
            <td><em>FirstBulletNumber</em></td>
            <td><em>DisplayMode</em></td>
         </tr>
         <tr>
            <td>
               <asp:ListBox ID="lbxBulletStyle" 
                  runat="server" AutoPostBack="true" 
                  onselectedindexchanged="lbxSelectedIndexChanged">
                  <asp:ListItem>NotSet</asp:ListItem>
                  <asp:ListItem>Numbered</asp:ListItem>
                  <asp:ListItem>LowerAlpha</asp:ListItem>
                  <asp:ListItem>UpperAlpha</asp:ListItem>
                  <asp:ListItem>LowerRoman</asp:ListItem>
                  <asp:ListItem>UpperRoman</asp:ListItem>
                  <asp:ListItem>Disc</asp:ListItem>
                  <asp:ListItem>Circle</asp:ListItem>
                  <asp:ListItem>Square</asp:ListItem>
                  <asp:ListItem>CustomImage</asp:ListItem>
               </asp:ListBox>
            </td>
            <td>
               <asp:ListBox ID="lbxBulletNumber" 
                  runat="server" AutoPostBack="true" 
                  onselectedindexchanged="lbxSelectedIndexChanged">
                  <asp:ListItem>1</asp:ListItem>
                  <asp:ListItem>2</asp:ListItem>
                  <asp:ListItem>3</asp:ListItem>
                  <asp:ListItem>4</asp:ListItem>
                  <asp:ListItem>5</asp:ListItem>
                  <asp:ListItem>6</asp:ListItem>
               </asp:ListBox>
            </td>
            <td>
               <asp:ListBox ID="lbxDisplayMode" 
                  runat="server" AutoPostBack="true"
                  onselectedindexchanged="lbxSelectedIndexChanged">
                  <asp:ListItem>Text</asp:ListItem>
                  <asp:ListItem>HyperLink</asp:ListItem>
                  <asp:ListItem>LinkButton</asp:ListItem>
               </asp:ListBox>
            </td>
         </tr>
      </table>
   </div>
   </form>
</body>
</html>

In Example 4-40, the BulletedList control has three ListItem objects in its Items collection, all added statically. It so happens that all the list items represent websites. In anticipation of the HyperLink DisplayMode being applied, each ListItem has its Value property set, which supplies the URL to navigate to. The Target property of the BulletedList control is set to _blank, which according to Table 4-5, will cause the new page to open in a new, unnamed browser window.

The OnClick attribute of the BulletedList control binds the Click event to the bltBooks_Click method in the code-behind file, shown highlighted in Example 4-41.

Example 4-41. BulletedListDemo.aspx.cs

using System;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class BulletedListDemo : Page
{
   protected void Page_Load(object sender, EventArgs e)
   {
      if (!IsPostBack)
      {
         //  Build 2 dimensional array for the lists
         //  First dimension contains bookname
         //  2nd dimension contains ISBN number
         string[,] books = { 
            {"Learning ASP.NET 2.0 with AJAX", "9780596513976"},
            {"Beginning ASP.NET 2.0 with C#", "9780470042583"},
            {"Programming C#","9780596527433"},
            {"Programming .NET 3.5","978059652756X"},
            {"Programming .NET Windows Applications","0596003218"},
            {"Programming ASP.NET 3e","0596001711"},
            {"WebClasses From Scratch","0789721260"},
            {"Teach Yourself C++ in 21 Days","067232072X"},
            {"Teach Yourself C++ in 10 Minutes","067231603X"},
            {"XML & Java From Scratch","0789724766"}, 
            {"XML Web Documents From Scratch","0789723166"},
            {"Clouds To Code","1861000952"},
            {"C++ Unleashed","0672312395"}
        };

         //  Now populate the list. 
         for (int i = 0; i < books.GetLength(0); i++)
         {
            //  Add both Text and Value          
            bltBooks.Items.Add(new ListItem(books[i, 0], 
               "http://www.amazon.com/gp/product/" + books[i, 1]));
         }
      }
   }

   protected void lbxSelectedIndexChanged(object sender, EventArgs e)
   {
      ListBox lb = (ListBox)sender;
      string strID = lb.ID;
      string strValue = lb.SelectedValue;

      switch (strID)
      {
         case "lbxBulletStyle": 
            BulletStyle style = 
               (BulletStyle)Enum.Parse(typeof(BulletStyle), strValue);
            bltBooks.BulletStyle = style;
            //  The CustomImage style is a special case.
            if (style == BulletStyle.CustomImage)
            {
               bltBooks.BulletImageUrl = "togglebutton_checked.gif";
            }
            break;

         case "lbxBulletNumber":
            bltBooks.FirstBulletNumber = Convert.ToInt32(strValue);
            break;

         case "lbxDisplayMode": 
            BulletedListDisplayMode displayMode = 
              (BulletedListDisplayMode)Enum.Parse
                 (typeof(BulletedListDisplayMode), strValue);
            bltBooks.DisplayMode = displayMode;
            break;

         default:
            break;
      }
   }
   protected void bltBooks_Click
      (object sender, BulletedListEventArgs e)
   {
      BulletedList b = (BulletedList)sender;
      tdMessage.InnerHtml = "Selected index: " +
         e.Index.ToString() + "<br />" + "Selected value: " +
         b.Items[e.Index].Value + "<br />";
   }
}

The event handler for this Click event will concatenate the Index and the Value properties of the clicked ListItem, along with some HTML elements, and assign that string to the InnerHtml property of an HTML server-side control. This event handler method requires an event argument of type BulletedListEventArgs, which exposes a single property, Index. This property returns the zero-based index of the clicked ListItem in the Items collection.

However, to retrieve the actual Text or Value of the clicked ListItem, you must have a reference to the specific BulletedList control that raised the event. In this example, there is only a single BulletedList control and the ID is known to us: bltList. However, a more generic technique is used here where a single event handler will work with any number of controls. You first cast the object that raised the event, encapsulated in sender, to an object of type BulletedList, and then index into the ListItems collection represented by the Items property of that BulletedList object. This is accomplished in the following line of code from Example 4-40:

BulletedList b = (BulletedList)sender;

Though not directly related to the BulletedList control, some interesting techniques are used with the ListBox controls on the page.

All three of the ListBox controls have AutoPostBack set to true, so you will see the results of changing a value immediately. Also, all three controls use the same event handler method, lbxSelectedIndexChanged, for the SelectedIndexChanged event.

In the lbxSelectedIndexChanged method in the code-behind file in Example 4-41, the first line of code gets a reference to the control that raised the event by casting sender to a ListBox object:

ListBox lb = (ListBox)sender;

Then the ID and SelectedValue properties of the listbox can be retrieved.

A switch block is used to take action appropriate for each listbox. The ListBox that sets the FirstBulletNumber property is straightforward, converting the SelectedValue, contained in the string variable strValue, to an integer and assigning that integer to the FirstBulletNumber property:

bltBooks.FirstBulletNumber = Convert.ToInt32(strValue);

The case blocks for the other two ListBoxes are a bit more interesting. The goal is to determine the item selected, either a BulletStyle or a DisplayMode, and apply that to the BulletedList. In both cases, this is accomplished using the static Enum.Parse method. This method converts a name or value of an enumerated constant into its equivalent enumerated object. You must pass it the type of the enumerated constant and the value of the constant.

So, looking at the case for lbxBulletStyle (lbxDisplayMode is equivalent), the Type of the enumeration is obtained from the typeof operator, which returns a System.Type object. The value of the selected constant is contained in strValue. Given these two arguments, Enum.Parse returns an object, which you then cast to the desired type and assign to a variable:

 BulletStyle style =
   (BulletStyle)Enum.Parse(typeof(BulletStyle), strValue);

This variable can then be used to set the appropriate property:

bltBooks.BulletStyle = style;

In the case of lbxBulletStyle, you must make a special case of the CustomImage style to assign the BulletImageUrl property. Here you can compare BulletStyle directly with the enumerated constants to see whether there is a match:

if (style == BulletStyle.CustomImage)
{
   bltBooks.BulletImageUrl = "togglebutton_checked.gif";
}

BulletedList extenders

It would be great if the ListSearchExtender demonstrated earlier could also be applied to a BulletedList control. Unfortunately, there is no scope for this, as a BulletedList doesn’t offer the user a place to type in her choice. However, the AJAX Control Toolkit contains the PagingBulletedListExtender (PBLE) control, as shown in Figure 4-25.

Rather than using user input to help find the correct choice in the list, the PBLE breaks the list into groups of choices based on two properties, IndexSize and MaxItemPerPage. It then adds an index above the list which the user can click to browse through the list more easily.

To re-create this, add to the C4_BasicControls website a new AJAX web form called BulletedListDemoWithAJAX.aspx. Copy to this new form the contents of the <div> element from BulletedListDemo.aspx under the ScriptManager in BulletedListDemoWithAJAX.aspx, and the event handlers from its code-behind page. Now add a PBLE to the new page under the main BulletedList control, bltBooks. Set its TargetControlId property to bltBooks, its ClientSort property to true, and its IndexSize to 3, and then run the page. See how the BulletedList is now augmented with an index which you can use to browse the list more efficiently.

The PagingBulletedListExtender control in action

Figure 4-25. The PagingBulletedListExtender control in action

Example 4-42 highlights the additions in BulletedListDemoWithAJAX.aspx over the original code in Example 4-40 to enable the PBLE. There are no changes in the code-behind file.

Example 4-42. BulletedListDemoWithAJAX.aspx

<%@ Page Language="C#" AutoEventWireup="true" 
   CodeFile="BulletedListDemoWithAJAX.aspx.cs"
   Inherits="BulletedListDemoWithAJAX" %>

<%@ Register Assembly="AjaxControlToolkit"
   Namespace="AjaxControlToolkit" TagPrefix="cc1" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>BulletedList Demo With AJAX</title>
    <script type="text/javascript">

      function pageLoad() {
      }

    </script>
</head>

<body>
   <form id="form1" runat="server">
   <div>
      <asp:ScriptManager ID="ScriptManager1" runat="server" />
      <asp:BulletedList ID="bltBooks" runat="server"
         Target="_blank" OnClick="bltBooks_Click" />
      <cc1:PagingBulletedListExtender ID="PagingBulletedListExtender1"
         runat="server" TargetControlID="bltBooks"
         ClientSort="true" IndexSize="3" />

      <table>
         ... as shown in Example 4-40 
      </table>
   </div>
   </form>
</body>
</html>

The PBLE has several read/write properties which all have an effect on how the index it generates is presented. These are shown in Table 4-20.

Table 4-20. PagingBulletedListExtender properties

Name

Type

Description

ClientSort

Boolean

Organizes the index entries alphabetically rather than leaving them to echo the order of the list items.

Height

Integer

Specifies a fixed height for the entries in the bulleted list.

IndexSize

Integer

Specifies the number of characters in each index entry. Has no effect if MaxItemPerPage is set.

MaxItemPerPage

Integer

Overrides IndexSize. Specifies the number of list items in each page of the list. The index entries will reflect the first item on each page.

SelectIndexCssClass

String

Sets the CSS class name for the index entry currently selected by the user.

UnselectIndexCssClass

String

Sets the CSS class name for any index entries not currently selected by the user.

Sliders and Ratings

The AJAX Control Toolkit introduces two new controls to web forms that are commonly used metaphors for a user’s feelings toward a purchase or service:

Slider

Presents the user with a sliding scale of values (e.g., 0-100) and a “handle” which the user can slide from left to right (or down to up) with the mouse to increase or decrease its value.

Ratings

Presents the user with a set of values which are often much smaller than those in a slider (e.g., 0-5) where each value is visually represented by one of two images depending on what the value is. For example, the AJAX Control Toolkit sample website uses filled and empty star images, much like you would see on Amazon.com, to reflect the current rating value.

It’s much easier to show these controls than to describe them. Figure 4-26 shows both of them in action in SlidersAndRatingsDemo.aspx, which you’ll build next.

Slider and Ratings controls in action

Figure 4-26. Slider and Ratings controls in action

To build the page, add to the website a new AJAX web form called SlidersAndRatingsDemo.aspx. Add a Ratings control to the form with some explanatory text.

Now you need to define how the current rating value will be displayed onscreen. You can tie four different CSS styles into a Ratings control, as listed in Table 4-21.

Tip

Because it’s customary for online ratings to be given in terms of “stars,” the Ratings control style properties are named as such for ease of use. However, this example just uses blocks of color defined in CSS rather than any particular images. The AJAX Control Toolkit sample website, on the other hand, does demonstrate a Ratings control using star images.

Table 4-21. Style properties for the Ratings controls

Property name

Purpose of CSS style

StarCssClass

Defines the generic style for a “star”—height, width, background color, etc.

FilledStarCssClass

Defines the style for a selected “star”.

EmptyStarCssClass

Defines the style for an unselected “star”.

WaitingStarCssClass

When the user changes the rating value, confirms to the user that it has recorded this new value by briefly changing (flashing) the style of the selected stars. This is the “flashing confirmation” style.

Create four CSS styles for these four mandatory properties and set them accordingly. The full markup for SlidersAndRatingsDemo.aspx in Example 4-43 shows one possibility.

Add a Button (btnSubmit) and a Label (lblChoices) to display the results of the rating, and then an event handler for the button’s Click handler, to update the Label control:

protected void btnSubmit_Click(object sender, EventArgs e)
{
   lblChoices.Text = String.Format("Pavarotti gets {0} stars",
     Rating1.CurrentRating.ToString());
}

Now run the form, change the rating, noting how the control uses the different styles. Click the button to see the current value of the Ratings control reflected on the page. Table 4-22 shows some optional properties for the Ratings control with which you can experiment.

Table 4-22. Optional properties for the Ratings control

Name

Type

Values

Description

CurrentRating

Integer

 

The initial rating for the Ratings control until the user changes it.

MaxRating

Integer

 

The maximum value for CurrentRating.

ReadOnly

Boolean

 

Set to true if CurrentRating should not be changed.

RatingAlign

Orientation

Horizontal, Vertical

Sets whether the stars should be set horizontally or stacked vertically. Default is Horizontal.

RatingDirection

RatingDirection

LeftToRightTopToBottom,RightToLeftBottomToTop

Sets which way to increase or decrease the CurrentRating value.

OnChanged

String

 

Client script that should run after the CurrentRating value has been changed.

The Slider control is actually an extender for a text box control, which stores the actual slider value. It also requires a second control, Label or Textbox, which is bound to it and displays the numeric value of the slider.

Add to the page two text boxes, called txtHiddenSlider and txtVisibleSlider, with empty text properties beneath the Ratings control. Now add the Slider extender to the page. Set the targetControlId and boundcontrolId properties to txtHiddenSlider and txtVisibleSlider, respectively. You can see the final markup for this page in Example 4-43. You’ll also need to update the Click event handler for the Button to reflect the slider’s value in the Label control, as shown in Example 4-44.

Example 4-43. SlidersAndRatingsDemo.aspx

<%@ Page Language="C#" AutoEventWireup="true"
   CodeFile="SlidersAndRatingsDemo.aspx.cs"
   Inherits="SlidersAndRatingsDemo" %>

<%@ Register Assembly="AjaxControlToolkit"
   Namespace="AjaxControlToolkit" TagPrefix="cc1" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
   <title>Slider and Ratings Demo</title>
   <script type="text/javascript">
      function pageLoad() {
      }
   </script>

   <style type="text/css">
      .ratingStar
      {
         font-size: 0pt;
         width: 25px;
         height: 25px;
         margin: 0px;
         padding: 0px;
         cursor: pointer;
         display: block;
         background-repeat: no-repeat;
      }
      .filledRatingStar
      {
         background-color: Black;
      }
      .emptyRatingStar
      {
         background-color: Yellow;
      }
      .savedRatingStar
      {
         background-color: Green;
      }
   </style>
</head>

<body>
   <form id="form1" runat="server">
   <div>
      <asp:ScriptManager ID="ScriptManager1" runat="server" />
      Rate Luciano Pavarotti :
      <cc1:Rating ID="Rating1" runat="server"
         StarCssClass="ratingStar"
         FilledStarCssClass="filledRatingStar"
         EmptyStarCssClass="emptyRatingStar"
         WaitingStarCssClass="savedRatingStar"
         CurrentRating="3" MaxRating="10" />
      <br />
      <br />
      How loud is he? :
      <asp:TextBox ID="txtHidden Slider" runat="server"></asp:TextBox>
      <asp:TextBox ID="txtVisibleSlider" runat="server"></asp:TextBox>      
      <cc1:SliderExtender ID="SliderExtender1" runat="server"
         TargetControlID="txtHiddenSlider"
         BoundControlID="txtVisibleSlider" />
      <br />
      <br />
      <asp:Label ID="lblChoices" runat="server" />
      <asp:Button ID="btnSubmit" runat="server" Text="Go"
         OnClick="btnSubmit_Click" />
   </div>
   </form>
</body>
</html>

Example 4-44. SlidersAndRatingsDemo.aspx.cs

using System;
using System.Web.UI;

public partial class SlidersAndRatingsDemo : Page
{
    protected void btnSubmit_Click(object sender, EventArgs e)
    {
       lblChoices.Text = String.Format
          ("Pavarotti rates {0}/{1} stars at {2} decibels",
           Rating1.CurrentRating.ToString(),
           Rating1.MaxRating.ToString(),
           txtHiddenSlider.Text);
    }
}

Run the page. Notice the value in the text box changes with the Slider. If you change the value in the TextBox, the Slider will update after the TextBox loses the focus. Try setting the slider’s Minimum and Maximum properties to adjust the value bounds on the slider, and the Steps property to a value greater than 1 for sliding up the values faster. Table 4-23 lays out all of the Slider’s optional properties.

Table 4-23. Properties for the Slider control

Name

Type

Values

Description

Decimals

Integer

 

Number of decimal places the slider value uses. Default is 0.

EnableHandleAnimation

Boolean

 

Enables or disables the animation of the slider handle after the user has manually changed the value in the bound TextBox. Default is false.

HandleCssClass

String

 

CSS class that defines an alternative look for the slider’s handle.

HandleImageUrl

String

 

URL for the image to be used as the slider’s handle.

Length

Integer

 

Width or height of the slider in pixels.

Maximum

Integer

 

Maximum value for the slider.

Minimum

Integer

 

Minimum value for the slider.

Orientation

SliderOrientation

Horizontal Vertical

The slider’s orientation.

RailsCssClass

String

 

CSS class that defines an alternative look for the slider’s rail.

RaiseChangeOnlyOn-MouseUp

Boolean

 

If true, a change event is raised only for the bound TextBox when the left mouse button dragging the slider has been raised.

Steps

Integer

 

Number of steps in the slider’s range. The default is the number of whole integers between Maximum and Minimum.

TooltipText

String

 

Text to display when the mouse pointer is held over the slider.

In the next chapter, we look at more advanced controls and compound controls.

Get Programming ASP.NET 3.5, 4th Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.