WHAT’S IN THIS CHAPTER?
WROX.COM CODE DOWNLOADS FOR THIS CHAPTER
Please note that all the code examples in this chapter are available as a part of this chapter’s code download on the book’s website at www.wrox.com on the Download Code tab.
Of the two types of server controls — HTML server controls and web server controls — the latter is considered the more powerful and flexible. The previous chapter looked at how to use HTML server controls in applications. HTML server controls enable you to manipulate HTML elements from your server-side code. On the other hand, web server controls are powerful because they are not explicitly tied to specific HTML elements; rather, they are more closely aligned to the specific functionality that you want to generate. As you will see throughout this chapter, web server controls can be very simple or rather complex depending on the control you are working with.
The purpose of the large collection of controls is to make you more productive. These controls give you advanced functionality that, in the past, you would have had to laboriously program or simply omit. In the classic ASP days, for example, few calendars were used on Internet websites. With the introduction of the Calendar server control in ASP.NET 1.0, calendar creation on a site became a trivial task. Building an image map on top of an image was another task that was difficult to achieve in ASP.NET 1.x, but this capability was introduced as a new server control in ASP.NET 2.0. As ASP.NET evolves through the releases, new controls and functionality are constantly added that help to make you a more productive web developer.
This chapter introduces some of the available web server controls. The first part of the chapter focuses on the web server controls that were around since the early days of ASP.NET. Then the chapter explores the server controls that were introduced after the initial release of ASP.NET. This chapter does not discuss every possible control because some server controls are introduced and covered in other chapters throughout the book.
The web server control is ASP.NET’s most-used component. Although you may have seen a lot of potential uses of the HTML server controls shown in the previous chapter, web server controls are definitely a notch higher in capability. They allow for a higher level of functionality that becomes more apparent as you work with them.
The HTML server controls provided by ASP.NET are translated to specific HTML elements. You control the output by working with the HTML attributes that the HTML element provides. The attributes can be changed dynamically on the server side before they are finally output to the client. There is a lot of power in this, and you have some HTML server control capabilities that you simply do not have when you work with web server controls.
Web server controls work differently. They do not map to specific HTML elements, but instead enable you to define functionality, capability, and appearance without the attributes that are available to you through a collection of HTML elements. When constructing a web page that is made up of web server controls, you are describing the functionality, the look-and-feel, and the behavior of your page elements. You then let ASP.NET decide how to output this construction. The output, of course, is based on the capabilities of the container that is making the request. This means that each requestor might see a different HTML output because each is requesting the same page with a different browser type or version. ASP.NET takes care of all the browser detection and the work associated with it on your behalf.
Unlike HTML server controls, web server controls are not only available for working with common web page form elements (such as textboxes and buttons), but they can also bring some advanced capabilities and functionality to your web pages. For instance, one common feature of many web applications is a calendar. No HTML form element places a calendar on your Web Forms, but a web server control from ASP.NET can provide your application with a full-fledged calendar, including some advanced capabilities. In the past, adding calendars to your web pages was not a small programming task. Today, adding calendars with ASP.NET is rather simple and is achieved with a single line of code!
Remember that when you are constructing your web server controls, you are actually constructing a control — a set of instructions — that is meant for the server (not the client). By default, all web server controls provided by ASP.NET use an asp prefix at the beginning of the control declaration. The following is a typical web server control:
<asp:Label ID="Label1" runat="server" Text="Hello World"></asp:Label>
Like HTML server controls, web server controls require an ID attribute to reference the control in the server-side code, as well as a runat="server" attribute declaration. As you do for other XML-based elements, you need to properly open and close web server controls using XML syntax rules. In the preceding example, you can see that the <asp:Label> control has a closing </asp:Label> element associated with it. You could have also closed this element using the following syntax:
<asp:Label ID="Label1" runat="server" Text="Hello World" />
The rest of this chapter examines some of the web server controls available to you in ASP.NET.
The Label server control is used to display text in the browser. Because this is a server control, you can dynamically alter the text from your server-side code. As you saw from the preceding examples of using the <asp:Label> control, the control uses the Text attribute to assign the content of the control as shown here:
<asp:Label ID="Label1" runat="server" Text="Hello World" />
Instead of using the Text attribute, however, you can place the content to be displayed between the <asp:Label> elements like this:
<asp:Label ID="Label1" runat="server">Hello World</asp:Label>
You can also provide content for the control through programmatic means, as illustrated in Listing 5-1.
LISTING 5-1: Programmatically providing text to the Label control
VB
Label1.Text = "Hello ASP.NET!"
C#
Label1.Text = "Hello ASP.NET!";
The Label server control has always been a control that simply showed text. Ever since ASP.NET 2.0, it has a little bit of extra functionality. The big change since this release of the framework is that you can give items in your form hot-key functionality (also known as accelerator keys). This causes the page to focus on a particular server control that you declaratively assign to a specific hot-key press (for example, using Alt+N to focus on the first textbox on the form).
A hot key is a quick way for the end user to initiate an action on the page. For instance, if you use Microsoft Internet Explorer, you can press Ctrl+N to open a new instance of IE. Hot keys have always been quite common in thick-client applications (Windows Forms), and now you can use them in ASP.NET. Listing 5-2 shows an example of how to give hot-key functionality to two textboxes on a form.
LISTING 5-2: Using the Label server control to provide hot-key functionality
<%@ Page Language="C#" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Label Server Control</title>
</head>
<body>
<form id="form1" runat="server">
<p>
<asp:Label ID="Label1" runat="server" AccessKey="N"
AssociatedControlID="Textbox1">User<u>n</u>ame</asp:Label>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
</p>
<p>
<asp:Label ID="Label2" runat="server" AccessKey="P"
AssociatedControlID="Textbox2"><u>P</u>assword</asp:Label>
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
</p>
<p>
<asp:Button ID="Button1" runat="server" Text="Submit" />
</p>
</form>
</body>
</html>
Hot keys are assigned with the AccessKey attribute. In this case, Label1 uses N, and Label2 uses P. The second attribute for the Label control is the AssociatedControlID attribute. The String value placed here associates the Label control with another server control on the form. The value must be one of the other server controls on the form. If not, the page gives you an error when invoked.
With these two controls in place, when the page is called in the browser, you can press Alt+N or Alt+P to automatically focus on a particular textbox in the form. In Figure 5-1, HTML-declared underlines indicate the letters to be pressed along with the Alt key to create focus on the control adjoining the text. This is not required, but it’s highly recommended because the end user expects this functionality when working with hot keys. In this example, the letter n in Username and the letter P in Password are underlined.
When working with hot keys, be aware that not all letters are available to use with the Alt key. Microsoft Internet Explorer already uses Alt+A, E, H, I, O, T, V, and W. If you use any of these letters, IE actions supersede any actions you place on the page.
The Literal server control works very much like the Label server control does. This control was always used in the past for text that you wanted to push out to the browser but keep unchanged in the process (a literal state). A Label control alters the output by placing <span> elements around the text as shown:
<span id="Label1">Here is some text</span>
The Literal control just outputs the text without the <span> elements. One feature found in this server control is the attribute Mode. This attribute enables you to dictate how the text assigned to the control is interpreted by the ASP.NET engine.
If you place some HTML code in the string that is output (for instance, <strong>Here is some text</strong>), the Literal control outputs just that, and the consuming browser shows the text as bold:
Here is some text
Try using the Mode attribute as illustrated here:
<asp:Literal ID="Literal1" runat="server" Mode="Encode"
Text="<strong>Here is some text</strong>"></asp:Literal>
Adding Mode="Encode" encodes the output before it is received by the consuming application:
<b>Label</b>
Now, instead of the text being converted to a bold font, the <strong> elements are displayed:
<strong>Here is some text</strong>
This is ideal if you want to display code in your application. Other values for the Mode attribute include Transform and PassThrough. Transform looks at the consumer and includes or removes elements as needed. For instance, not all devices accept HTML elements, so, if the value of the Mode attribute is set to Transform, these elements are removed from the string before it is sent to the consuming application. A value of PassThrough for the Mode property means that the text is sent to the consuming application without any changes being made to the string.
One of the main features of web pages is to offer forms that end users can use to submit their information for collection. The TextBox server control is one of the most used controls in this space. As its name suggests, the control provides a textbox on the form that enables the end user to input text. You can map the TextBox control to three different HTML elements used in your forms.
First, the TextBox control can be used as a standard HTML textbox, as shown in the following code snippet:
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
This code creates a textbox on the form that looks like the one shown in Figure 5-2.
Second, the TextBox control can allow end users to input their passwords into a form. This is done by changing the TextMode attribute of the TextBox control to Password, as illustrated here:
<asp:TextBox ID="TextBox1" runat="server" TextMode="Password"></asp:TextBox>
When asking end users for their passwords through the browser, it is best practice to provide a textbox that encodes the content placed in this form element. Using an attribute and value of TextMode="Password" ensures that the text is encoded with a star (*) or a dot, as shown in Figure 5-3.
Third, the TextBox server control can be used as a multiline textbox. The code for accomplishing this task is as follows:
<asp:TextBox ID="TextBox1" runat="server" TextMode="MultiLine" Width="300px"
Height="150px"></asp:TextBox>
Giving the TextMode attribute a value of MultiLine creates a multilined textbox in which the end user can enter a larger amount of text in the form. The Width and Height attributes set the size of the text area, but these are optional attributes — without them, the text area is produced in its smallest size. Figure 5-4 shows the use of the preceding code after adding some text.
When working with a multilined textbox, be aware of the Wrap attribute. When set to True (which is the default), the text entered into the text area wraps to the next line if needed. When set to False, the end user can type continuously in a single line until she presses the Enter key, which brings the cursor down to the next line.
Because the TextBox server control is derived from the base class of WebControl, one of the methods available to it is Focus(). The Focus() method enables you to dynamically place the end user’s cursor in an appointed form element (not just the TextBox control, but in any of the server controls derived from the WebControl class). With that said, it is probably most often used with the TextBox control, as illustrated in Listing 5-3.
LISTING 5-3: Using the Focus() method with the TextBox control
VB
Protected Sub Page_Load(sender As Object, e As EventArgs)
FirstNameTextBox.Focus()
End Sub
C#
protected void Page_Load(Object sender, EventArgs e)
{
FirstNameTextBox.Focus();
}
When the page using this method is loaded in the browser, the cursor is already placed inside of the textbox, ready for you to start typing. There is no need to move your mouse to get the cursor in place so you can start entering information in the form. This is ideal for those folks who take a keyboard approach to working with forms.
ASP.NET pages work in an event-driven way. When an action on a web page triggers an event, server-side code is initiated. One of the more common events is an end user clicking a button on the form. If you double-click the button in Design view of Visual Studio 2012, you can see the code page with the structure of the Button1_Click event already in place. This is because OnClick is the most common event of the Button control. Double-clicking the TextBox control constructs an OnTextChanged event. This event is triggered when the end user moves the cursor focus outside the textbox, either by clicking another element on the page after entering something into a textbox, or by simply tabbing out of the textbox. The use of this event is shown in Listing 5-4.
LISTING 5-4: Triggering an event when a TextBox change occurs
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub TextBox1_TextChanged(sender As Object, e As EventArgs)
Response.Write("OnTextChanged event triggered")
End Sub
Protected Sub Button1_Click(sender As Object, e As EventArgs)
Response.Write("OnClick event triggered")
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Triggering an event when a TextBox</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="TextBox1" runat="server" AutoPostBack="True"
OnTextChanged="TextBox1_TextChanged"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Button"
OnClick="Button1_Click" />
</div>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void TextBox1_TextChanged(object sender, EventArgs e)
{
Response.Write("OnTextChanged event triggered");
}
protected void Button1_Click(object sender, EventArgs e)
{
Response.Write("OnClick event triggered");
}
</script>
As you build and run this page, notice that you can type something in the textbox, but once you tab out of it, the OnTextChanged event is triggered and the code contained in the TextBox1_TextChanged event runs. To make this work, you must add the AutoPostBack attribute to the TextBox control and set it to True. This causes the web page to look for any text changes prior to an actual page postback. For the AutoPostBack feature to work, the browser viewing the page must support ECMAScript.
You want the forms you build for your web applications to be as simple to use as possible. You want to make them easy and quick for the end user to fill out the information and proceed. If you make a form too onerous, the people who come to your site may leave without completing it.
One of the great capabilities for any Web Form is smart auto-completion. You may have seen this yourself when you visited a site for the first time. As you start to fill out information in a form, a drop-down list appears below the textbox as you type, showing you a value that you have typed in a previous form. The plain textbox you were working with has become a smart textbox. Figure 5-5 shows an example of this feature.
A great aspect of the TextBox control is the AutoCompleteType attribute, which enables you to apply the auto-completion feature to your own forms. You have to help the textboxes on your form to recognize the type of information that they should be looking for. What does that mean? To answer this, first look at the possible values of the AutoCompleteType attribute:
Disabled | Company | HomeFax |
BusinessCity | DisplayName | Homepage |
BusinessCountryRegion | HomeState | HomePhone |
BusinessFax | HomeStreetAddress | JobTitle |
BusinessPhone | HomeZipCode | LastName |
BusinessState | MiddleName | |
BusinessStreetAddress | Enabled | Notes |
BusinessUrl | FirstName | Office |
BusinessZipCode | Gender | Pager |
Cellular | HomeCity | Search |
Department | HomeCountryRegion |
From this list, you can see that if your textbox is asking for the end user’s home street address, you want to use the following in your TextBox control:
<asp:TextBox ID="TextBox1" runat="server"
AutoCompleteType="HomeStreetAddress"></asp:TextBox>
As you view the source of the textbox you created, you can see that the following construction has occurred:
<input name="TextBox1" type="text" vcard_name="vCard.Home.StreetAddress"
id="TextBox1" />
This feature makes your forms easier to work with. Yes, it is a simple thing but sometimes the little things keep visitors coming back again and again to your website.
Another common control for your Web Forms is a button that can be constructed using the Button server control. Buttons are the usual element used to submit forms. Most of the time you are simply dealing with items contained in your forms through the Button control’s OnClick event, as illustrated in Listing 5-5.
LISTING 5-5: The Button control’s OnClick event
VB
Protected Sub Button1_Click(sender As Object, e As EventArgs)
'Code here
End Sub
C#
protected void Button1_Click(object sender, EventArgs e)
{
// Code here
}
The Button control is one of the easier controls to use, but there are a couple of properties of which you must be aware: CausesValidation and CommandName. They are discussed in the following sections.
If you have more than one button on your web page and you are working with the validation server controls, you may not want to fire the validation for each button on the form. Setting the CausesValidation property to False is a way to use a button that will not fire the validation process. This is explained in more detail in Chapter 6.
You can have multiple buttons on your form all working from a single event. The nice thing is that you can also tag the buttons so that the code can make logical decisions based on which button on the form was clicked. You must construct your Button controls in the manner illustrated in Listing 5-6 to take advantage of this behavior.
LISTING 5-6: Constructing multiple button controls to work from a single function
<asp:Button ID="Button1" runat="server" OnCommand="Button_Command"
CommandName="DoSomething1" Text="Button 1" />
<asp:Button ID="Button2" runat="server" OnCommand="Button_Command"
CommandName="DoSomething2" Text="Button 2" />
Looking at these two instances of the Button control, you should pay attention to several things. The first thing to notice is what is not present — any attribute mention of an OnClick event. Instead, you use the OnCommand event, which points to an event called Button_Command. You can see that both Button controls are working from the same event. How does the event differentiate between the two buttons being clicked? Through the value placed in the CommandName property. In this case, they are indeed separate values — DoSomething1 and DoSomething2.
The next step is to create the Button_Command event to deal with both these buttons by simply typing one out or by selecting the Command event from the drop-down list of available events for the Button control from the Code view of Visual Studio. In either case, you should end up with an event like the one shown in Listing 5-7.
LISTING 5-7: The Button_Command event
VB
Protected Sub Button_Command(ByVal sender As Object,
ByVal e As System.Web.UI.WebControls.CommandEventArgs)
Select Case e.CommandName
Case "DoSomething1"
Response.Write("Button 1 was selected")
Case "DoSomething2"
Response.Write("Button 2 was selected")
End Select
End Sub
C#
protected void Button_Command(object sender,
System.Web.UI.WebControls.CommandEventArgs e)
{
switch (e.CommandName)
{
case ("DoSomething1"):
Response.Write("Button 1 was selected");
break;
case ("DoSomething2"):
Response.Write("Button 2 was selected");
break;
}
}
Notice that this method uses System.Web.UI.WebControls.CommandEventArgs instead of the typical System.EventArgs. This gives you access to the member CommandName used in the Select Case (switch) statement as e.CommandName. With this object, you can check for the value of the CommandName property used by the button that was clicked on the form and take a specific action based upon the value passed.
You can add some parameters to be passed in to the Command event beyond what is defined in the CommandName property. You do this by using the Button control’s CommandArgument property. Adding values to the property enables you to define items a bit more granularly if you want. You can get at this value via server-side code using e.CommandArgument from the CommandEventArgs object.
Buttons are frequently used for submitting information and causing actions to occur on a web page. Before ASP.NET 1.0/1.1, people intermingled quite a bit of JavaScript in their pages to fire JavaScript events when a button was clicked. The process became more cumbersome in ASP.NET 1.0/1.1, but ever since ASP.NET 2.0, it has been much easier.
You can create a page that has a JavaScript event, as well as a server-side event, triggered when the button is clicked, as illustrated in Listing 5-8.
LISTING 5-8: Two types of events for the button
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
Response.Write("Postback!")
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Button Server Control</title>
</head>
<body>
<form id="form1" runat="server">
<asp:Button ID="Button1" runat="server" Text="Button"
OnClientClick="AlertHello()" OnClick="Button1_Click" />
</form>
<script type="text/javascript">
function AlertHello() {
alert('Hello ASP.NET');
}
</script>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void Button1_Click(Object sender, EventArgs e)
{
Response.Write("Postback!");
}
</script>
The first thing to notice is the attribute for the Button server control: OnClientClick. It points to the client-side function, unlike the OnClick attribute that points to the server-side event. This example uses a JavaScript function called AlertHello().
One cool thing about Visual Studio 2012 is that it can work with server-side script tags that are right alongside client-side script tags. It all works together seamlessly. In the example, after the JavaScript alert dialog box is issued (see Figure 5-6) and the end user clicks OK, the page posts back as the server-side event is triggered.
Another interesting attribute for the Button server controls is PostBackUrl. It enables you to perform cross-page posting, instead of simply posting your ASP.NET pages back to the same page, as shown in the following example:
<asp:Button ID="Button1" runat="server" Text="Submit to Another Page"
PostBackUrl="Page2.aspx" />
Cross-page posting is covered in greater detail in Chapter 3.
The LinkButton server control is a variation of the Button control. It is the same except that the LinkButton control takes the form of a hyperlink. Nevertheless, it is not a typical hyperlink. When the end user clicks the link, it behaves like a button.
A LinkButton server control is constructed as follows:
<asp:LinkButton ID="LinkButton1" Runat="server" OnClick="LinkButton1_Click">
Submit your name to our database
</asp:LinkButton>
Using the LinkButton control gives you the results shown in Figure 5-7.
The ImageButton control is also a variation of the Button control. It is almost exactly the same as the Button control, except that it enables you to use a custom image as the form’s button instead of the typical buttons used on most forms. This means that you can create your own buttons as images, and the end users can click the images to submit form data. A typical construction of the ImageButton is as follows:
<asp:ImageButton ID="ImageButton1" runat="server"
OnClick="ImageButton1_Click" ImageUrl="search.jpg" />
The ImageButton control specifies the location of the image in use via the ImageUrl property. From this example, you can see that the ImageUrl points to search.jpg. The big difference between the ImageButton control and the LinkButton or Button controls is that ImageButton takes a different construction for the OnClick event. It is shown in Listing 5-9.
LISTING 5-9: The Click event for the ImageButton control
VB
Protected Sub ImageButton1_Click(sender As Object, e As ImageClickEventArgs)
'Code here
End Sub
C#
protected void ImageButton1_Click(object sender, ImageClickEventArgs e)
{
// Code here
}
The construction uses the ImageClickEventArgs object instead of the System.EventArgs object usually used with the LinkButton and Button controls. You can use this object to determine where in the image the end user clicked by using both e.X and e.Y coordinates.
The HyperLink server control enables you to programmatically work with any hyperlinks on your web pages. Hyperlinks are links that allow end users to transfer from one page to another. You can set the text of a hyperlink using the control’s Text attribute:
<asp:HyperLink ID="HyperLink1" runat="server" Text="Go to this page here"
NavigateUrl="Default2.aspx"></asp:HyperLink>
This server control creates a hyperlink on your page with the text Go to this page here. When the link is clicked, the user is redirected to the value that is placed in the NavigateUrl property (in this case, the Default2.aspx page).
The interesting thing about the HyperLink server control is that it can be used for images as well as text. Instead of the Text attribute, it uses the ImageUrl property:
<asp:HyperLink ID="HyperLink2" runat="server" ImageUrl="MyLinkImage.gif"
NavigateUrl="Default2.aspx"></asp:HyperLink>
The HyperLink control is a great way to dynamically place hyperlinks on a web page based either upon user input in a form or on database values that are retrieved when the page is loaded.
The DropDownList server control enables you to place an HTML select box on your web page and program against it. It is ideal when you have a large collection of items from which you want the end user to select a single item. It is usually used for a medium- to large-sized collection. If the collection size is relatively small, consider using the RadioButtonList server control (described later in this chapter).
The select box generated by the DropDownList control displays a single item and allows the end user to make a selection from a larger list of items. Depending on the number of choices available in the select box, the end user may have to scroll through a list of items. Note that the appearance of the scroll bar in the drop-down list is automatically created by the browser depending on the browser version and the number of items contained in the list.
Here is the code for a DropDownList control:
<asp:DropDownList ID="DropDownList1" runat="server">
<asp:ListItem>Select an Item</asp:ListItem>
<asp:ListItem>Car</asp:ListItem>
<asp:ListItem>Airplane</asp:ListItem>
<asp:ListItem>Train</asp:ListItem>
</asp:DropDownList>
This code generates a drop-down list in the browser, as shown in Figure 5-8.
The DropDownList control comes in handy when you start binding it to various data stores. The data stores can be arrays, database values, XML file values, or values found elsewhere. For an example of binding the DropDownList control, this next example looks at dynamically generating a DropDownList control from one of three available arrays, as shown in Listing 5-10.
LISTING 5-10: Dynamically generating a DropDownList control from an array
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub DropDownList1_SelectedIndexChanged(ByVal sender As Object,
ByVal e As System.EventArgs)
Dim CarArray() As String = {"Ford", "Honda", "BMW", "Dodge"}
Dim AirplaneArray() As String = {"Boeing 777", "Boeing 747", "Boeing 737"}
Dim TrainArray() As String = {"Bullet Train", "Amtrack", "Tram"}
If DropDownList1.SelectedValue = "Car" Then
DropDownList2.DataSource = CarArray
ElseIf DropDownList1.SelectedValue = "Airplane" Then
DropDownList2.DataSource = AirplaneArray
ElseIf DropDownList1.SelectedValue = "Train" Then
DropDownList2.DataSource = TrainArray
End If
DropDownList2.DataBind()
DropDownList2.Visible = (DropDownList1.SelectedValue <> _
"Select an Item")
End Sub
Protected Sub Button1_Click(ByVal sender As Object,
ByVal e As System.EventArgs)
Response.Write("You selected <b>" & _
DropDownList1.SelectedValue.ToString() & ": " &
DropDownList2.SelectedValue.ToString() & "</b>")
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>DropDownList Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
Select transportation type:<br />
<asp:DropDownList ID="DropDownList1" runat="server"
OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged"
AutoPostBack="true">
<asp:ListItem>Select an Item</asp:ListItem>
<asp:ListItem>Car</asp:ListItem>
<asp:ListItem>Airplane</asp:ListItem>
<asp:ListItem>Train</asp:ListItem>
</asp:DropDownList>
<asp:DropDownList ID="DropDownList2" runat="server" Visible="false">
</asp:DropDownList>
<asp:Button ID="Button1" runat="server" Text="Select Options"
OnClick="Button1_Click" />
</div>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
string[] carArray = new[] { "Ford", "Honda", "BMW", "Dodge" };
string[] airplaneArray = new[] {"Boeing 777", "Boeing 747",
"Boeing 737"};
string[] trainArray = new[] { "Bullet Train", "Amtrack", "Tram" };
if (DropDownList1.SelectedValue == "Car")
{
DropDownList2.DataSource = carArray;
}
else if (DropDownList1.SelectedValue == "Airplane")
{
DropDownList2.DataSource = airplaneArray;
}
else if (DropDownList1.SelectedValue == "Train")
{
DropDownList2.DataSource = trainArray;
}
DropDownList2.DataBind();
DropDownList2.Visible = DropDownList1.SelectedValue != "Select an Item";
}
protected void Button1_Click(object sender, EventArgs e)
{
Response.Write("You selected <b>" +
DropDownList1.SelectedValue.ToString() + ": " +
DropDownList2.SelectedValue.ToString() + "</b>");
}
</script>
In this example, the second drop-down list is dynamically generated based upon the value selected from the first drop-down list. For instance, selecting Car from the first drop-down list dynamically creates a second drop-down list on the form that includes a list of available car selections.
This is possible because of the use of the AutoPostBack feature of the DropDownList control. When the AutoPostBack property is set to True, the method provided through the OnSelectedIndexChanged event is fired when a selection is made. In the example, the DropDownList1_SelectedIndexChanged event is fired, dynamically creating the second drop-down list.
In this method, the content of the second drop-down list is created in a string array and then bound to the second DropDownList control through the use of the DataSource property and the DataBind() method.
When built and run, this page looks like the one shown in Figure 5-9.
The DropDownList, ListBox, CheckBoxList, and RadioButtonList server controls give you the capability to visually remove items from the collection displayed in the control, although you can still work with the items that are not displayed in your server-side code.
For a quick example of removing items, create a drop-down list with three items, including one that you will not display. On the postback, however, you can still work with the ListItem’s Value or Text property, as illustrated in Listing 5-11.
LISTING 5-11: Disabling certain ListItems from a collection
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub DropDownList1_SelectedIndexChanged(ByVal sender As Object,
ByVal e As System.EventArgs)
Response.Write("You selected item number " &
DropDownList1.SelectedValue & "<br>")
Response.Write("You didn't select item number " &
DropDownList1.Items(1).Value)
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>DropDownList Server Control</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:DropDownList ID="DropDownList1" runat="server"
AutoPostBack="True"
OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged">
<asp:ListItem Value="1">First Choice</asp:ListItem>
<asp:ListItem Value="2" Enabled="False">Second
Choice</asp:ListItem>
<asp:ListItem Value="3">Third Choice</asp:ListItem>
</asp:DropDownList>
</div>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
Response.Write("You selected item number " +
DropDownList1.SelectedValue + "<br>");
Response.Write("You didn't select item number " +
DropDownList1.Items[1].Value);
}
</script>
From the code, you can see that the ListItem server control element has an attribute: Enabled. The boolean value given to this element dictates whether an item in the collection is displayed. If you use Enabled="False", the item is not displayed, but you still have the capability to work with the item in the server-side code displayed in the DropDownList1_SelectedIndexChanged event. The result of the output from these Response.Write statements is shown in Figure 5-10.
The ListBox server control has a function similar to the DropDownList control. It displays a collection of items. The ListBox control behaves differently from the DropDownList control in that it displays more of the collection to the end user, and it enables the end user to make multiple selections from the collection — something that is not possible with the DropDownList control.
A typical ListBox control appears in code as follows:
<asp:ListBox ID="ListBox1" runat="server">
<asp:ListItem>ASP.NET 4.5</asp:ListItem>
<asp:ListItem>ASP.NET MVC 4</asp:ListItem>
<asp:ListItem>jQuery 1.8.x</asp:ListItem>
<asp:ListItem>Visual Studio 2012</asp:ListItem>
</asp:ListBox>
This generates the browser display illustrated in Figure 5-11.
You can use the SelectionMode attribute to let your end users make multiple selections from what is displayed by the ListBox control. Here’s an example:
<asp:ListBox ID="ListBox1" runat="server" SelectionMode="Multiple">
<asp:ListItem>ASP.NET 4.5</asp:ListItem>
<asp:ListItem>ASP.NET MVC 4</asp:ListItem>
<asp:ListItem>jQuery 1.8.x</asp:ListItem>
<asp:ListItem>Visual Studio 2012</asp:ListItem>
</asp:ListBox>
The possible values of the SelectionMode property include Single and Multiple. Setting the value to Multiple allows the end user to make multiple selections in the list box. The user must hold down either the Ctrl or Shift keys while making selections. Holding down the Ctrl key enables the user to make a single selection from the list while maintaining previous selections. Holding down the Shift key enables a range of multiple selections.
The ListBox control shown in Listing 5-12 allows multiple selections to be displayed in the browser when a user clicks the Submit button. The form should also have an additional textbox and button at the top that enables the end user to add additional items to the ListBox.
LISTING 5-12: Using the ListBox control
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub Button1_Click(ByVal sender As Object,
ByVal e As System.EventArgs)
ListBox1.Items.Add(TextBox1.Text.ToString())
End Sub
Protected Sub Button2_Click(ByVal sender As Object,
ByVal e As System.EventArgs)
Label1.Text = "You selected from the ListBox:<br>"
For Each li As ListItem In ListBox1.Items
If li.Selected = True Then
Label1.Text += li.Text & "<br>"
End If
Next
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Using the ListBox</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Add an additional item"
OnClick="Button1_Click" /><br />
<br />
<asp:ListBox ID="ListBox1" runat="server" SelectionMode="Multiple">
<asp:ListItem>ASP.NET 4.5</asp:ListItem>
<asp:ListItem>ASP.NET MVC 4</asp:ListItem>
<asp:ListItem>jQuery 1.8.x</asp:ListItem>
<asp:ListItem>Visual Studio 2012</asp:ListItem>
</asp:ListBox><br />
<br />
<asp:Button ID="Button2" runat="server" Text="Submit"
OnClick="Button2_Click" /><br />
<br />
<asp:Label ID="Label1" runat="server"></asp:Label>
</div>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void Button1_Click(object sender, EventArgs e)
{
ListBox1.Items.Add(TextBox1.Text.ToString());
}
protected void Button2_Click(object sender, EventArgs e)
{
Label1.Text = "You selected from the ListBox:<br>";
foreach (ListItem li in ListBox1.Items)
{
if (li.Selected)
{
Label1.Text += li.Text + "<br>";
}
}
}
</script>
This is an interesting example. First, some default items (four commonly used products in ASP.NET web development) are already placed inside the ListBox control. However, the textbox and button at the top of the form allow the end user to add products to the list. Users can then make one or more selections from the ListBox, including selections from the items that they dynamically added to the collection. After a user makes his or her selection and clicks the button, the Button2_Click event iterates through the ListItem instances in the collection and displays only the items that have been selected.
This control works by creating an instance of a ListItem object and using its Selected property to see if a particular item in the collection has been selected. The use of the ListItem object is not limited to the ListBox control (although that is what is used here). You can dynamically add or remove items from a collection and get at items and their values using the ListItem object in the DropDownList, CheckBoxList, and RadioButtonList controls as well. It is a list-control feature. When this page is built and run, you get the results presented in Figure 5-12.
To add items to the collection, you can use the following short syntax:
ListBox1.Items.Add(TextBox1.Text)
Look at the source code created in the browser, and you should see something similar to the following generated dynamically:
<select size="4" name="ListBox1" multiple="multiple" id="ListBox1">
<option value="ASP.NET 4.5">ASP.NET 4.5</option>
<option value="ASP.NET MVC 4">ASP.NET MVC 4</option>
<option value="jQuery 1.8.x">jQuery 1.8.x</option>
<option value="Visual Studio 2012">Visual Studio 2012</option>
<option value="Modernizr 2.6.x">Modernizr 2.6.x</option>
</select>
You can see that the dynamically added value is a text item, and you can see its value. You can also add instances of the ListItem object to get different values for the item name and value:
VB
ListBox1.Items.Add(New ListItem("Modernizr 2.6.x", "Modernizr"))
C#
ListBox1.Items.Add(new ListItem("Modernizr 2.6.x", "Modernizr"));
This example adds a new instance of the ListItem object — adding not only the textual name and version of the item, but also the value of the item (its name only). It produces the following results in the browser:
<option value="Modernizr">Modernizr 2.6.x</option>
Check boxes on a web form enable your users to make selections from a collection of items or to specify a value of an item to be yes/no, on/off, or true/false. Use either the CheckBox control or the CheckBoxList control to include check boxes in your Web Forms.
The CheckBox control allows you to place single check boxes on a form; the CheckBoxList control allows you to place collections of check boxes on the form. You can use multiple CheckBox controls on your ASP.NET pages, but each check box is treated as its own element with its own associated events. On the other hand, the CheckBoxList control allows multiple check boxes and specific events for the entire group.
Listing 5-13 shows an example of using the CheckBox control.
LISTING 5-13: Using a single instance of the CheckBox control
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub CheckBox1_CheckedChanged(ByVal sender As Object,
ByVal e As System.EventArgs)
Response.Write("Thanks for your donation!")
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>CheckBox control</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:CheckBox ID="CheckBox1" runat="server" Text="Donate $10 to my cause!"
OnCheckedChanged="CheckBox1_CheckedChanged" AutoPostBack="true" />
</div>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void CheckBox1_CheckedChanged(object sender, EventArgs e)
{
Response.Write("Thanks for your donation!");
}
</script>
This produces a page that contains a single check box asking for a monetary donation. Using the CheckedChanged event, OnCheckedChanged is used within the CheckBox control. The attribute’s value points to the CheckBox1_CheckedChanged event, which fires when the user checks the check box. It occurs only if the AutoPostBack property is set to True (this property is set to False by default). Running this page produces the results shown in Figure 5-13.
You might not want to use the AutoPostBack feature of the check box, but instead want to determine if the check box is checked after the form is posted back to the server. You can make this check through an If Then statement, as illustrated in the following example:
VB
If (CheckBox1.Checked = True) Then
Response.Write("Thanks for your donation!")
End If
C#
if (CheckBox1.Checked == true)
{
Response.Write("Thanks for your donation!");
}
This check is done on the CheckBox value using the control’s Checked property. The property’s value is a boolean value, so it is either True (checked) or False (not checked).
You can also use the Checked property to make sure a check box is checked based on other dynamic values:
VB
If (Member = True) Then
CheckBox1.Checked = True
End If
C#
if (Member == true)
{
CheckBox1.Checked = true;
}
In the previous check box example, the text appears to the right of the actual check box, as shown in Figure 5-14.
Using the CheckBox control’s TextAlign property, you can realign the text so that it appears on the other side of the check box:
<asp:CheckBox ID="CheckBox1" runat="server" Text="Donate $10 to my cause!"
OnCheckedChanged="CheckBox1_CheckedChanged" AutoPostBack="true"
TextAlign="Left" />
The possible values of the TextAlign property are Right (the default setting) and Left. This property is also available to the CheckBoxList, RadioButton, and RadioButtonList controls. Assigning the value Left produces the result shown in Figure 5-15.
The CheckBoxList server control is quite similar to the CheckBox control, except that the former enables you to work with a collection of items rather than a single item. The idea is that a CheckBoxList server control instance is a collection of related items, each being a check box unto itself.
To see the CheckBoxList control in action, you can build an example that uses Microsoft’s SQL Server to pull information from the Customer table of the AdventureWorks sample database. An example is presented in Listing 5-14.
LISTING 5-14: Dynamically populating a CheckBoxList
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub Button1_Click(ByVal sender As Object,
ByVal e As System.EventArgs)
Label1.Text = "You selected:<br>"
For Each li As ListItem In CheckBoxList1.Items
If li.Selected = True Then
Label1.Text += li.Text & "<br>"
End If
Next
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>CheckBoxList control</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="Button1" runat="server" Text="Submit Choices"
OnClick="Button1_Click" /><br />
<br />
<asp:Label ID="Label1" runat="server"></asp:Label>
<br />
<asp:CheckBoxList ID="CheckBoxList1" runat="server"
DataSourceID="SqlDataSource1" DataTextField="CompanyName"
RepeatColumns="3" BorderColor="Black"
BorderStyle="Solid" BorderWidth="1px">
</asp:CheckBoxList>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
SelectCommand="SELECT DISTINCT TOP 12 [CompanyName]
FROM [SalesLT].[Customer] ORDER BY [CompanyName]"
ConnectionString="
<%$ ConnectionStrings:AdventureWorksConnectionString %>">
</asp:SqlDataSource>
</div>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = "You selected:<br>";
foreach (ListItem li in CheckBoxList1.Items)
{
if (li.Selected == true)
{
Label1.Text += li.Text + "<br>";
}
}
}
</script>
This ASP.NET page has a SqlDataSource control on the page that pulls the information you need from the Adventure Works database. From the SELECT statement used in this control, you can see that you are retrieving the CompanyName field from the top 10 unique listings in the Customer table.
The CheckBoxList control binds itself to the SqlDataSource control using a few properties:
<asp:CheckBoxList ID="CheckBoxList1" runat="server"
DataSourceID="SqlDataSource1" DataTextField="CompanyName"
RepeatColumns="3" BorderColor="Black"
BorderStyle="Solid" BorderWidth="1px">
</asp:CheckBoxList>
The DataSourceID property is used to associate the CheckBoxList control with the results that come back from the SqlDataSource control. Then the DataTextField property is used to retrieve the name of the field you want to work with from the results. In this example, there is only one that is available: the CompanyName. That’s it! CheckBoxList generates the results you want.
The remaining code consists of styling properties, which are pretty interesting. The BorderColor, BorderStyle, and BorderWidth properties enable you to put a border around the entire check box list. The most interesting property is the RepeatColumns property, which specifies how many columns (three in this example) can be used to display the results.
When you run the page, you get the results shown in Figure 5-16.
The RepeatDirection property instructs the CheckBoxList control about how to lay out the items bound to the control on the web page. Possible values include Vertical and Horizontal. The default value is Vertical. Setting it to Vertical with a RepeatColumn setting of 3 gives the following results:
CheckBox1 | CheckBox4 | CheckBox7 |
CheckBox2 | CheckBox5 | CheckBox8 |
CheckBox3 | CheckBox6 | CheckBox9 |
When the RepeatDirection property is set to Horizontal, you get the check box items laid out in a horizontal fashion:
CheckBox1 | CheckBox2 | CheckBox3 |
CheckBox4 | CheckBox5 | CheckBox6 |
CheckBox7 | CheckBox8 | CheckBox9 |
The RadioButton server control is quite similar to the CheckBox server control. It places a radio button on your web page. Unlike a check box, however, a single radio button on a form does not make much sense. Radio buttons are generally form elements that require at least two options. A typical set of RadioButton controls on a page takes the following construction:
<asp:RadioButton ID="RadioButton1" runat="server" Text="Yes" GroupName="Set1" />
<asp:RadioButton ID="RadioButton2" runat="server" Text="No" GroupName="Set1"/>
Figure 5-17 shows the result.
When you look at the code for the RadioButton control, note the standard Text property that places the text next to the radio button on the web form. The more important property here is GroupName, which can be set in one of the RadioButton controls to match what it is set to in the other. This enables the radio buttons on the web form to work together for the end user. How do they work together? Well, when one of the radio buttons on the form is checked, the circle associated with the item selected appears filled in. Any other filled-in circle from the same group in the collection is removed, ensuring that only one of the radio buttons in the collection is selected.
Listing 5-15 shows an example of using the RadioButton control.
LISTING 5-15: Using the RadioButton server control
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub RadioButton_CheckedChanged(ByVal sender As Object,
ByVal e As System.EventArgs)
If RadioButton1.Checked = True Then
Response.Write("You selected Visual Basic")
Else
Response.Write("You selected C#")
End If
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>RadioButton control</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:RadioButton ID="RadioButton1" runat="server" Text="Visual Basic"
GroupName="LanguageChoice"
OnCheckedChanged="RadioButton_CheckedChanged"
AutoPostBack="True" />
<asp:RadioButton ID="RadioButton2" runat="server" Text="C#"
GroupName="LanguageChoice"
OnCheckedChanged="RadioButton_CheckedChanged"
AutoPostBack="True" />
</div>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void RadioButton_CheckedChanged(object sender, EventArgs e)
{
if (RadioButton1.Checked == true)
{
Response.Write("You selected Visual Basic");
}
else
{
Response.Write("You selected C#");
}
}
</script>
Like the CheckBox, the RadioButton control has a CheckedChanged event that puts an OnCheckedChanged attribute in the control. The attribute’s value points to the server-side event that is fired when a selection is made using one of the two radio buttons on the form. Remember that the AutoPostBack property needs to be set to True for this to work correctly.
Figure 5-18 shows the results.
One advantage that the RadioButton control has over a RadioButtonList control (which is discussed next) is that it enables you to place other items (text, controls, or images) between the RadioButton controls themselves. RadioButtonList, however, is always a straight list of radio buttons on your web page.
The RadioButtonList server control lets you display a collection of radio buttons on a web page. The RadioButtonList control is quite similar to the CheckBoxList and other list controls in that it allows you to iterate through to see what the user selected, to make counts, or to perform other actions.
A typical RadioButtonList control is written to the page in the following manner:
<asp:RadioButtonList ID="RadioButtonList1" runat="server">
<asp:ListItem Selected="True">English</asp:ListItem>
<asp:ListItem>Russian</asp:ListItem>
<asp:ListItem>Finnish</asp:ListItem>
<asp:ListItem>Swedish</asp:ListItem>
</asp:RadioButtonList>
Like the other list controls, this one uses instances of the ListItem object for each of the items contained in the collection. From the example, you can see that if the Selected property is set to True, one of the ListItem objects is selected by default when the page is generated for the first time. This produces the results shown in Figure 5-19.
The Selected property is not required, but it is a good idea if you want the end user to make some sort of selection from this collection. Using it makes it impossible to leave the collection blank.
You can use the RadioButtonList control to check for the value selected by the end user in any of your page methods. Listing 5-16 shows a Button1_Click event that pushes out the value selected in the RadioButtonList collection.
LISTING 5-16: Checking the value of the item selected from a RadioButtonList control
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub Button1_Click(ByVal sender As Object,
ByVal e As System.EventArgs)
Label1.Text = "You selected: " &
RadioButtonList1.SelectedItem.ToString()
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>RadioButtonList Control</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="Label1" runat="server" />
<asp:RadioButtonList ID="RadioButtonList1" runat="server">
<asp:ListItem Selected="True">English</asp:ListItem>
<asp:ListItem>Russian</asp:ListItem>
<asp:ListItem>Finnish</asp:ListItem>
<asp:ListItem>Swedish</asp:ListItem>
</asp:RadioButtonList>
<asp:Button ID="Button1" runat="server" Text="Submit"
OnClick="Button1_Click" />
</div>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = "You selected: " + RadioButtonList1.SelectedItem.ToString();
}
</script>
This bit of code gets at the item selected from the RadioButtonList collection of ListItem objects. It is how you work with other list controls that are provided in ASP.NET. The RadioButtonList also affords you access to the RepeatColumns and RepeatDirection properties (these were explained in the CheckBoxList section). You can bind this control to items that come from any of the data source controls so that you can dynamically create radio button lists on your web pages.
The Image server control enables you to work with the images that appear on your web page from the server-side code. It is a simple server control, but it can give you the power to determine how your images are displayed on the browser screen. A typical Image control is constructed in the following manner:
<asp:Image ID="Image1" runat="server" ImageUrl="~/Images/Windows.jpg" />
The important property here is ImageUrl. It points to the file location of the image. In this case, the location is specified as the Windows.jpg file.
Listing 5-17 shows an example of how to change the ImageUrl property dynamically.
LISTING 5-17: Changing the ImageUrl property dynamically
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub Button1_Click(ByVal sender As Object,
ByVal e As System.EventArgs)
Image1.ImageUrl = "~/Images/Windows8.jpg"
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Image Control</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Image ID="Image1" runat="server"
ImageUrl="~/Images/Windows.jpg" /><br />
<br />
<asp:Button ID="Button1" runat="server" Text="Change Image"
OnClick="Button1_Click" />
</div>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void Button1_Click(object sender, EventArgs e)
{
Image1.ImageUrl = "~/Images/Windows8.jpg";
}
</script>
In this example, an image (Windows.jpg) is shown in the browser when the page is loaded for the first time. When the end user clicks the button on the page, a new image (Windows8.jpg) is loaded in the postback process.
Special circumstances can prevent end users from viewing an image that is part of your web page. They might be physically unable to see the image, or they might be using a text-only browser. In these cases, their browsers look for the <img> element’s longdesc attribute that points to a file containing a long description of the image that is displayed.
For these cases, the Image server control includes a DescriptionUrl attribute. The value assigned to it is a text file that contains a thorough description of the image with which it is associated. Here is how to use it:
<asp:Image ID="Image1" runat="server" ImageUrl="~/Images/Windows.jpg"
DescriptionUrl="~/WindowsImage.txt" />
This code produces the following results in the browser:
<img id="Image1" src="Images/Windows.jpg" longdesc="WindowsImage.txt" />
Remember that the image does not support the user clicking the image. If you want to program events based on button clicks, use the ImageButton server control discussed earlier in this chapter.
Tables are one of the web page’s more common elements because the HTML <table> element is one of the most common formats utilized for displaying numerous records of information. The typical construction of the Table server control is as follows:
<asp:Table ID="Table1" runat="server">
<asp:TableRow ID="TableRow1" runat="server" Font-Bold="True"
ForeColor="White" BackColor="DarkGray">
<asp:TableHeaderCell>First Name</asp:TableHeaderCell>
<asp:TableHeaderCell>Last Name</asp:TableHeaderCell>
</asp:TableRow>
<asp:TableRow>
<asp:TableCell>Jason</asp:TableCell>
<asp:TableCell>Gaylord</asp:TableCell>
</asp:TableRow>
<asp:TableRow>
<asp:TableCell>Scott</asp:TableCell>
<asp:TableCell>Hanselman</asp:TableCell>
</asp:TableRow>
<asp:TableRow>
<asp:TableCell>Todd</asp:TableCell>
<asp:TableCell>Miranda</asp:TableCell>
</asp:TableRow>
<asp:TableRow>
<asp:TableCell>Pranav</asp:TableCell>
<asp:TableCell>Rastogi</asp:TableCell>
</asp:TableRow>
</asp:Table>
This produces the simple two-rowed table shown in Figure 5-20.
You can do a lot with the Table server control. For example, you can dynamically add rows to the table, as illustrated in Listing 5-18.
LISTING 5-18: Dynamically adding rows to the table
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Dim tr As New TableRow()
Dim fname As New TableCell()
fname.Text = "Christian"
tr.Cells.Add(fname)
Dim lname As New TableCell()
lname.Text = "Wenz"
tr.Cells.Add(lname)
Table1.Rows.Add(tr)
End Sub
</script>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
TableRow tr = new TableRow();
TableCell fname = new TableCell();
fname.Text = "Christian";
tr.Cells.Add(fname);
TableCell lname = new TableCell();
lname.Text = "Wenz";
tr.Cells.Add(lname);
Table1.Rows.Add(tr);
}
</script>
To add a single row to a Table control, you have to create new instances of the TableRow and TableCell objects. You create the TableCell objects first and then place them within a TableRow object that is added to a Table object.
The Table server control obviously contains some extra features beyond what has been presented. One of the simpler features is the capability to add captions to the tables on web pages. Figure 5-21 shows a table with a caption.
To give your table a caption, simply use the Caption attribute in the Table control, as illustrated in Listing 5-19.
LISTING 5-19: Using the Caption attribute
<%@ Page Language="C#" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Table Server Control</title>
</head>
<body>
<form id="form1" runat="server">
<asp:Table ID="Table1" runat="server"
Caption="<b>Table 1:</b> This is an example of a caption above a
table."
BackColor="Gainsboro">
<asp:TableRow ID="Tablerow1" runat="server">
<asp:TableCell ID="Tablecell1" runat="server">
Lorem ipsum dolor sit
amet, consectetuer adipiscing elit. Duis vel justo. Aliquam
adipiscing. In mattis volutpat urna. Donec adipiscing, nisl ege
dictum egestas, felis nulla ornare ligula, ut bibendum pede aug
eu augue. Sed vel risus nec urna pharetra imperdiet. Aenean
semper. Sed ullamcorper auctor sapien. Suspendisse luctus. Ut a
nibh. Nam lorem. Aliquam dictum aliquam purus.
</asp:TableCell>
</asp:TableRow>
</asp:Table>
</form>
</body>
</html>
By default, the caption is placed at the top center of the table, but you can control where it is placed by using another attribute — CaptionAlign. Its settings include Bottom, Left, NotSet, Right, and Top.
In the early days of ASP.NET, an <asp:Table> element contained any number of <asp:TableRow> elements. In ASP.NET 4.5, you can nest some additional elements within the <asp:Table> element. These elements include <asp:TableHeaderRow> and <asp:TableFooterRow>. They add either a header or footer to your table, enabling you to use the Table server control to page through lots of data but still retain some text in place to indicate the type of data being handled. This is quite a powerful feature when you work with mobile applications that dictate that sometimes end users can move through only a few records at a time.
The Calendar server control is a rich control that enables you to place a full-featured calendar directly on your web pages. It allows for a high degree of customization to ensure that it looks and behaves in a unique manner. The Calendar control, in its simplest form, is coded in the following manner:
<asp:Calendar ID="Calendar1" runat="server"></asp:Calendar>
This code produces a calendar on your web page without any styles added, as shown in Figure 5-22.
The calendar allows you to navigate through the months of the year and to select specific days in the exposed month. A simple application that enables the user to select a day of the month is shown in Listing 5-20.
LISTING 5-20: Selecting a single day in the Calendar control
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub Calendar1_SelectionChanged(ByVal sender As Object,
ByVal e As System.EventArgs)
Response.Write("You selected: " &
Calendar1.SelectedDate.ToShortDateString())
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Using the Calendar Control</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Calendar ID="Calendar1" runat="server"
OnSelectionChanged="Calendar1_SelectionChanged"></asp:Calendar>
</div>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void Calendar1_SelectionChanged(object sender, EventArgs e)
{
Response.Write("You selected: " +
Calendar1.SelectedDate.ToShortDateString());
}
</script>
Running this application pulls up the calendar in the browser. The end user can then select a single date in it. After a date is selected, the Calendar1_SelectionChanged event is triggered and makes use of the OnSelectionChange attribute. This event writes the value of the selected date to the screen. The result is shown in Figure 5-23.
When you use the Calendar1_SelectionChanged event, the selected date is written out using the ToShortDateString() method. The Calendar control also allows you to write out the date in a number of other formats, as detailed in the following list:
By default, the Calendar control enables you to make single day selections. You can use the SelectionMode property to change this behavior to allow your users to make week or month selections from the calendar instead. The possible values of this property include Day, DayWeek, DayWeekMonth, and None.
The Day setting enables you to click a specific day in the calendar to highlight it (this is the default). When you use the setting of DayWeek, you can still make individual day selections, but you can also click the arrow next to the week (see Figure 5-24) to make selections that consist of an entire week. Using the setting of DayWeekMonth lets users make individual day selections or week selections. A new arrow appears in the upper-left corner of the calendar that enables users to select an entire month (also shown in Figure 5-24). A setting of None means that it is impossible for the end user to make any selections, which is useful for calendars on your site that are informational only.
Even if an end user makes a selection that encompasses an entire week or an entire month, you get back from the selection only the first date of this range. If, for example, you allow users to select an entire month and one selects October 2012, what you get back (using ToShortDateString()) is 10/1/2012 — the first date in the date range of the selection. That might work for you, but if you require all the dates in the selected range, Listing 5-21 shows you how to get them.
LISTING 5-21: Retrieving a range of dates from a selection
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub Calendar1_SelectionChanged(ByVal sender As Object,
ByVal e As System.EventArgs)
Label1.Text = "<b><u>You selected the following date/dates:</u></b><br>"
For i As Integer = 0 To (Calendar1.SelectedDates.Count - 1)
Label1.Text += Calendar1.SelectedDates.Item(i).ToShortDateString() &
"<br>"
Next
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Using the Calendar Control</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Calendar ID="Calendar1" runat="server"
OnSelectionChanged="Calendar1_SelectionChanged"
SelectionMode="DayWeekMonth"></asp:Calendar>
<p>
<asp:Label ID="Label1" runat="server"></asp:Label>
</p>
</div>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void Calendar1_SelectionChanged(object sender, EventArgs e)
{
Label1.Text = "<b><u>You selected the following date/dates:</u></b><br>";
for (int i = 0; i < Calendar1.SelectedDates.Count; i++)
{
Label1.Text += Calendar1.SelectedDates[i].ToShortDateString() +
"<br>";
}
}
</script>
In this example, the Calendar control lets users make selections that can be an individual day, a week, or even a month. Using a For Next loop, you iterate through a selection by using the SelectedDates.Count property. The code produces the results shown in Figure 5-25.
You can get just the first day of the selection by using the following:
VB
Calendar1.SelectedDates.Item(0).ToShortDateString()
C#
Calendar1.SelectedDates[0].ToShortDateString();
And you can get the last date in the selected range by using:
VB
Calendar1.SelectedDates.Item(Calendar1.SelectedDates.Count-1).ToShortDateString()
C#
Calendar1.SelectedDates[Calendar1.SelectedDates.Count-1].ToShortDateString();
As you can see, this is possible using the Count property of the SelectedDates object.
There is a lot to the Calendar control — definitely more than can be covered in this chapter. One nice thing about the Calendar control is the ease of extensibility that it offers. Begin exploring new ways to customize this control further by looking at one of the easiest ways to change it — applying a style to the control.
Using Visual Studio, you can give the controls a new look-and-feel from the Design view of the page you are working with. Highlight the Calendar control and open the control’s smart tag to see the Auto Format link. That gives you a list of available styles that can be applied to your Calendar control.
Some of the styles are shown in Figure 5-26.
In addition to changing the style of the Calendar control, you can work with the control during its rendering process. The Calendar control includes an event called DayRender that allows you to control how a single date or all the dates in the calendar are rendered. Listing 5-22 shows an example of how to change one of the dates being rendered in the calendar.
LISTING 5-22: Controlling how a day is rendered in the calendar
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub Calendar1_DayRender(ByVal sender As Object,
ByVal e As System.Web.UI.WebControls.DayRenderEventArgs)
e.Cell.VerticalAlign = VerticalAlign.Top
If (e.Day.DayNumberText = "25") Then
e.Cell.Controls.Add(New LiteralControl("<p>User Group Meeting!</p>"))
e.Cell.BorderColor = Drawing.Color.Black
e.Cell.BorderWidth = 1
e.Cell.BorderStyle = BorderStyle.Solid
e.Cell.BackColor = Drawing.Color.LightGray
End If
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Using the Calendar Control</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Calendar ID="Calendar1" runat="server"
OnDayRender="Calendar1_DayRender" Height="190px"
BorderColor="White"
Width="350px" ForeColor="Black" BackColor="White" BorderWidth="1px"
NextPrevFormat="FullMonth" Font-Names="Verdana" Font-Size="9pt">
<SelectedDayStyle ForeColor="White"
BackColor="#333399"></SelectedDayStyle>
<OtherMonthDayStyle ForeColor="#999999"></OtherMonthDayStyle>
<TodayDayStyle BackColor="#CCCCCC"></TodayDayStyle>
<NextPrevStyle ForeColor="#333333" VerticalAlign="Bottom"
Font-Size="8pt" Font-Bold="True"></NextPrevStyle>
<DayHeaderStyle Font-Size="8pt" Font-Bold="True"></DayHeaderStyle>
<TitleStyle ForeColor="#333399" BorderColor="Black"
Font-Size="12pt" Font-Bold="True"
BackColor="White" BorderWidth="4px">
</TitleStyle>
</asp:Calendar>
</div>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void Calendar1_DayRender(object sender, DayRenderEventArgs e)
{
e.Cell.VerticalAlign = VerticalAlign.Top;
if (e.Day.DayNumberText == "18")
{
e.Cell.Controls.Add(new LiteralControl("<p>User Group Meeting!</p>"));
e.Cell.BorderColor = System.Drawing.Color.Black;
e.Cell.BorderWidth = 1;
e.Cell.BorderStyle = BorderStyle.Solid;
e.Cell.BackColor = System.Drawing.Color.LightGray;
}
}
</script>
In this example, you use a Calendar control with a little style to it. When the page is built and run in the browser, you can see that the 18th of every month in the calendar has been changed by the code in the Calendar1_DayRender event. The calendar is shown in Figure 5-27.
The Calendar control in this example adds an OnDayRender attribute that points to the Calendar1_DayRender event. The method is run for each of the days rendered in the calendar. The class constructor shows that you are not working with the typical System.EventArgs class, but instead with the DayRenderEventArgs class. It gives you access to each of the days rendered in the calendar.
The two main properties from the DayRenderEventArgs class are Cell and Day. The Cell property gives you access to the space in which the day is being rendered, and the Day property gives you access to the specific date being rendered in the cell.
From the actions being taken in the Calendar1_DayRender event, you can see that both properties are used. First, the Cell property sets the vertical alignment of the cell to Top. If it didn’t, the table might look a little strange when one of the cells has content. Next, a check is made to determine if the day being rendered (checked with the Day property) is the 25th of the month. If it is, the If Then statement runs using the Cell property to change the styling of just that cell. The styling change adds a control, as well as makes changes to the border and color of the cell.
As you can see, working with individual dates in the calendar is fairly straightforward. You can easily give them the content and appearance you want.
A nice feature of the Day property is that you can turn off the option to select a particular date or range of dates by setting the Day property’s IsSelectable property to False:
VB
Public Sub Calendar1_DayRender(sender As Object, e As DayRenderEventArgs)
If (e.Day.Date < DateTime.Now) Then
e.Day.IsSelectable = False
End If
End Sub
C#
public void Calendar1_DayRender(Object sender, DayRenderEventArgs e)
{
if (e.Day.Date < DateTime.Now)
{
e.Day.IsSelectable = false;
}
}
Although web users find ads rather annoying, advertising continues to be prevalent everywhere on the web. With the AdRotator control, you can configure your application to show a series of advertisements to the end users. With this control, you can use advertisement data from sources other than the standard XML file that was used with the early versions of this control.
If you are using an XML source for the ad information, first create an XML advertisement file. The advertisement file allows you to incorporate some elements that give you a lot of control over the appearance and behavior of your ads. Listing 5-23 shows an example of an XML advertisement file.
LISTING 5-23: The XML advertisement file
<?xml version="1.0" encoding="utf-8" ?>
<Advertisements
xmlns="http://schemas.microsoft.com/AspNet/AdRotator-Schedule-File">
<Ad>
<ImageUrl>book1.jpg</ImageUrl>
<NavigateUrl>http://www.wrox.com</NavigateUrl>
<AlternateText>Beginning ASP.NET</AlternateText>
<Impressions>50</Impressions>
<Keyword>ASP.NET</Keyword>
</Ad>
<Ad>
<ImageUrl>book2.jpg</ImageUrl>
<NavigateUrl>http://www.wrox.com</NavigateUrl>
<AlternateText>Beginning Visual C#</AlternateText>
<Impressions>50</Impressions>
<Keyword>C#</Keyword>
</Ad>
</Advertisements>
This XML file, used for storing information about the advertisements that appear in your application, has just a few elements detailed in Table 5-1. Remember that all elements are optional.
ELEMENT | DESCRIPTION |
ImageUrl | Takes a string value that indicates the location of the image to use. |
NavigateUrl | Takes a string value that indicates the URL to post to when the image is clicked. |
AlternateText | Takes a string value that is used for display if images are turned off in the client’s browser or if the image is not found. |
Impressions | Takes a numerical value that indicates the likelihood of the image being selected for display. |
Keyword | Takes a string value that sets the category of the image in order to allow for the filtering of ads. |
Now that the XML advertisement file is in place, you can simply use the AdRotator control to read from this file. Listing 5-24 shows an example of this in action.
LISTING 5-24: Using the AdRotator control as a banner ad
<%@ Page Language="C#" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>AdRotator Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:AdRotator ID="AdRotator1" runat="server"
AdvertisementFile="Listing05-23.xml" />
<p>
Lorem ipsum dolor sit
amet, consectetuer adipiscing elit. Duis vel justo. Aliquam
adipiscing. In mattis volutpat urna. Donec adipiscing, nisl eget
dictum egestas, felis nulla ornare ligula, ut bibendum pede augue
eu augue. Sed vel risus nec urna pharetra imperdiet. Aenean
semper. Sed ullamcorper auctor sapien. Suspendisse luctus. Ut ac
nibh. Nam lorem. Aliquam dictum aliquam purus.
</p>
</div>
</form>
</body>
</html>
The example shows the ad specified in the XML advertisement file as a banner ad at the top of the page.
You are not required to place all your ad information in the XML advertisement file. Instead, you can use another data source to which you bind the AdRotator. For instance, you bind the AdRotator to a SqlDataSource object that is retrieving the ad information from SQL Server in the following fashion:
<asp:AdRotator ID="AdRotator1" runat="server"
DataSourceId="SqlDataSource1" AlternateTextField="AlternateTF"
ImageUrlField="Image" NavigateUrlField="NavigateUrl" />
The AlternateTextField, ImageUrlField, and NavigateUrlField properties point to the column names that are used in SQL Server for those items.
The Xml server control provides a means of getting XML and transforming it using an XSL style sheet. The Xml control can work with your XML in a couple of ways. The simplest method is by using the construction shown in Listing 5-25.
LISTING 5-25: Displaying an XML document
<asp:Xml ID="Xml1" runat="server" DocumentSource="Food.xml"
TransformSource="FoodTemplate.xslt"></asp:Xml>
This method takes only a couple of attributes to make it work: DocumentSource, which points to the path of the XML file, and TransformSource, which provides the XSLT file to use in transforming the XML document.
The other way to use the Xml server control is to load the XML into an object and then pass the object to the Xml control, as illustrated in Listing 5-26.
LISTING 5-26: Loading the XML file to an object before providing it to the Xml control
VB
<%@ Page Language="VB" %>
<%@ Import Namespace="System.Xml.Xsl" %>
<%@ Import Namespace="System.Xml.XPath" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub Page_Load(sender As Object, e As EventArgs)
Dim MyXmlDoc = New XPathDocument(Server.MapPath("Food.xml"))
Dim MyXsltDoc = New XslTransform()
MyXsltDoc.Load(Server.MapPath("FoodTemplate.xslt"))
Xml1.XPathNavigator = MyXmlDoc.CreateNavigator()
Xml1.Transform = MyXsltDoc
End Sub
</script>
C#
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Xml.Xsl" %>
<%@ Import Namespace="System.Xml.XPath" %>
<!DOCTYPE html>
<script runat="server">
protected void Page_Load(Object sender, EventArgs e)
{
XPathDocument MyXmlDoc = new XPathDocument(Server.MapPath("Food.xml"));
XslTransform MyXsltDoc = new XslTransform();
MyXsltDoc.Load(Server.MapPath("FoodTemplate.xslt"));
Xml1.XPathNavigator = MyXmlDoc.CreateNavigator();
Xml1.Transform = MyXsltDoc;
}
</script>
To make this work, you have to ensure that the System.Xml and System.Xml.Xsl namespaces are imported into your page. The example loads both the XML and XSL files and then assigns these files as the values of the Document and Transform properties.
The Panel server control encapsulates a set of controls you can use to manipulate or lay out your ASP.NET pages. It is basically a wrapper for other controls, enabling you to take a group of server controls along with other elements (such as HTML and images) and turn them into a single unit.
The advantage of using the Panel control to encapsulate a set of other elements is that you can manipulate these elements as a single unit using one attribute set in the Panel control itself. For example, setting the Font-Bold attribute to True causes each item within the Panel control to adopt this attribute.
The Panel control also has the capability to scroll with scrollbars that appear automatically depending on the amount of information that Panel control holds. You can even specify how the scrollbars should appear.
For an example of using scrollbars, look at a long version of the Lorem Ipsum text (found at www.lipsum.com) and place that text within the Panel control, as shown in Listing 5-27.
LISTING 5-27: Using the Scrollbar feature with the Panel server control
<%@ Page Language="C#" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Panel Server Control Page</title>
</head>
<body>
<form id="form1" runat="server">
<asp:Panel ID="Panel1" runat="server" Height="300" Width="300"
ScrollBars="auto">
<p>Lorem ipsum dolor sit amet . . . </p>
</asp:Panel>
</form>
</body>
</html>
By assigning values to the Height and Width attributes of the Panel server control and using the ScrollBars attribute (in this case, set to Auto), you can display the information it contains within the defined area using scrollbars (see Figure 5-28).
As you can see, a single vertical scrollbar has been added to the set area of 300 × 300 pixels. The Panel control wraps the text by default as required. To change this behavior, use the Wrap attribute, which takes a boolean value:
<asp:Panel ID="Panel1" runat="server" Height="300" Width="300"
ScrollBars="auto" Wrap="False" />
Turning off wrapping may cause the horizontal scrollbar to turn on (depending on what is contained in the panel section).
If you do not want to let the ASP.NET engine choose which scrollbars to activate, you can actually make that decision by using the ScrollBars attribute. In addition to Auto, its values include None, Horizontal, Vertical, and Both.
Another interesting attribute that enables you to change the behavior of the Panel control is HorizontalAlign. It enables you to set how the content in the Panel control is horizontally aligned. The possible values of this attribute include NotSet, Center, Justify, Left, and Right. Figure 5-29 shows a collection of Panel controls with different horizontal alignments.
It is also possible to move the vertical scrollbar to the left side of the Panel control by using the Direction attribute. Direction can be set to NotSet, LeftToRight, and RightToLeft. A setting of RightToLeft is ideal when you are dealing with languages that are written from right to left (some Asian languages, for example). However, that setting also moves the scrollbar to the left side of the Panel control. If the scrollbar is moved to the left side and the HorizontalAlign attribute is set to Left, your content resembles Figure 5-30.
The PlaceHolder server control works just as its name implies — it is a placeholder for you to interject objects dynamically into your page. Think of it as a marker with which you can add other controls. The capability to add controls to a page at a specific point also works with the Panel control.
To see how it works, insert a PlaceHolder control into your page and then add controls to it from your server-side code in the manner shown in Listing 5-28.
LISTING 5-28: Using the PlaceHolder server control to add controls to a page dynamically
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub Page_Load(sender As Object, e As EventArgs)
Dim MyNameLabel As New Label()
MyNameLabel.Text = "Welcome, Jason!"
PlaceHolder1.Controls.Add(MyNameLabel)
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>PlaceHolder Control</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:PlaceHolder ID="PlaceHolder1" runat="server" />
</div>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void Page_Load(Object sender, EventArgs e)
{
Label MyNameLabel = new Label();
MyNameLabel.Text = "Welcome, Jason!";
PlaceHolder1.Controls.Add(MyNameLabel);
}
</script>
This example creates a new instance of a Label control and populates it with a value before it is added to the PlaceHolder control. You can add more than one control to a single instance of a PlaceHolder control.
One common HTML web page element is a collection of items in a bulleted list. The BulletedList server control is meant to display a bulleted list of items easily in an ordered (using the HTML <ol> element) or unordered (using the HTML <ul> element) fashion. In addition, the control can determine the style used for displaying the list.
The BulletedList control can be constructed of any number of <asp:ListItem> controls or can be data-bound to a data source of some kind and populated based upon the contents retrieved. Listing 5-29 shows a bulleted list in its simplest form.
LISTING 5-29: A simple BulletedList control
<%@ Page Language="C#" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>BulletedList Server Control</title>
</head>
<body>
<form id="form1" runat="server">
<asp:BulletedList ID="Bulletedlist1" runat="server">
<asp:ListItem>United States</asp:ListItem>
<asp:ListItem>United Kingdom</asp:ListItem>
<asp:ListItem>Finland</asp:ListItem>
<asp:ListItem>Russia</asp:ListItem>
<asp:ListItem>Sweden</asp:ListItem>
<asp:ListItem>Estonia</asp:ListItem>
</asp:BulletedList>
</form>
</body>
</html>
The use of the <asp:BulletedList> element, along with <asp:ListItem> elements, produces a simple bulleted list output like the one shown in Figure 5-31.
The BulletedList control also enables you to easily change the style of the list with just one or two attributes. The BulletStyle attribute changes the style of the bullet that precedes each line of the list. It has possible values of Numbered, LowerAlpha, UpperAlpha, LowerRoman, UpperRoman, Disc, Circle, Square, NotSet, and CustomImage. Figure 5-32 shows examples of these styles (minus the CustomImage setting that enables you to use any image of your choice).
You can change the starting value of the first item in any of the numbered styles (Numbered, LowerAlpha, UpperAlpha, LowerRoman, UpperRoman) by using the FirstBulletNumber attribute. If you set the attribute’s value to 5 when you use the UpperRoman setting, for example, you get the format illustrated in Figure 5-33.
To employ images as bullets, use the CustomImage setting in the BulletedList control. You must also use the BulletImageUrl attribute in the following manner:
<asp:BulletedList ID="Bulletedlist1" BulletStyle="CustomImage"
BulletImageUrl="~/search.jpg" runat="server">
Figure 5-34 shows an example of image bullets.
The BulletedList control has an attribute called DisplayMode, which has three possible values: Text, HyperLink, and LinkButton. Text is the default and has been used so far in the examples. Using Text means that the items in the bulleted list are laid out only as text. HyperLink means that each of the items is turned into a hyperlink — any user clicking the link is redirected to another page, which is specified by the <asp:ListItem> control’s Value attribute. A value of LinkButton turns each bulleted list item into a hyperlink that posts back to the same page. It enables you to retrieve the selection that the end user makes, as illustrated in Listing 5-30.
LISTING 5-30: Using the LinkButton value for the DisplayMode attribute
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub BulletedList1_Click(sender As Object, e As BulletedListEventArgs)
Label1.Text = "The index of item you selected: " & e.Index & _
"<br>The value of the item selected: " & _
BulletedList1.Items(e.Index).Text
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>BulletedList Server Control</title>
</head>
<body>
<form id="form1" runat="server">
<asp:BulletedList ID="BulletedList1" runat="server"
OnClick="BulletedList1_Click" DisplayMode="LinkButton">
<asp:ListItem>United States</asp:ListItem>
<asp:ListItem>United Kingdom</asp:ListItem>
<asp:ListItem>Finland</asp:ListItem>
<asp:ListItem>Russia</asp:ListItem>
<asp:ListItem>Sweden</asp:ListItem>
<asp:ListItem>Estonia</asp:ListItem>
</asp:BulletedList>
<asp:Label ID="Label1" runat="server">
</asp:Label>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void BulletedList1_Click(object sender, BulletedListEventArgs e)
{
Label1.Text = "The index of item you selected: " + e.Index +
"<br>The value of the item selected: " +
BulletedList1.Items[e.Index].Text;
}
</script>
In this example, the DisplayMode attribute is set to LinkButton, and the OnClick attribute is used to point to the BulletedList1_Click event. BulletedList1_Click uses the BulletedListEventArgs object, which only exposes the Index property. Using that, you can determine the index number of the item selected.
You can directly access the Text value of a selected item by using the Items property, or you can use the same property to populate an instance of the ListItem object, as shown here:
VB
Dim blSelectedValue As ListItem = BulletedList1.Items(e.Index)
C#
ListItem blSelectedValue = BulletedList1.Items[e.Index];
Now that you have seen how to create bulleted lists with items that you declaratively place in the code, look at how to create dynamic bulleted lists from items that are stored in a data store. The following example shows how to use the BulletedList control to data-bind to results coming from a data store; in it, all information is retrieved from an XML file.
The first step is to create the XML in Listing 5-31.
LISTING 5-31: An XML listing of books
<?xml version="1.0" encoding="utf-8" ?>
<Books>
<Book
Title="Professional ASP.NET 4.5"
Year="2013"
Price="$59.99" />
<Book
Title="Beginning ASP.NET 4.5"
Year="2012"
Price="$59.99" />
<Book
Title="Beginning Visual C#"
Year="2012"
Director="$59.99" />
</Books>
To populate the BulletedList server control with the Title attribute from the Listing05-31.xml file, use an XmlDataSource control to access the file, as illustrated in Listing 5-32.
LISTING 5-32: Dynamically populating a BulletedList server control
<%@ Page Language="C#" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>BulletedList Server Control</title>
</head>
<body>
<form id="form1" runat="server">
<asp:BulletedList ID="BulletedList1" runat="server"
DataSourceID="XmlDataSource1" DataTextField="Title">
</asp:BulletedList>
<asp:XmlDataSource ID="XmlDataSource1" runat="server"
DataFile="~/Listing05-31.xml" XPath="Books/Book"></asp:XmlDataSource>
</form>
</body>
</html>
In this example, you use the DataSourceID attribute to point to the XmlDataSource control (as you would with any control that can be bound to one of the data source controls). After you are connected to the data source control, you specifically point to the Title attribute using the DataTextField attribute. After the two server controls are connected and the page is run, you get a bulleted list that is completely generated from the contents of the XML file. Figure 5-35 shows the result.
For many years now, developers have been using hidden fields in their web pages to work with state management. The <input type="hidden"> element is ideal for storing items that have no security context to them. These items are simply placeholders for data points that you want to store in the page itself instead of using the Session object or intermingling the data with the view state of the page. ViewState (discussed in more detail in Chapter 7) is another great way to store information in a page, but many developers turn off this feature to avoid corruption of the ViewState or possible degradation of page performance.
Any time a hidden field is placed within a web page, it is not interpreted in the browser in any fashion, although it is completely viewable by end users if they look at the source of the HTML page.
Listing 5-33 is an example of using the HiddenField server control to hold a GUID that can be used from page to page simply by carrying over its value as the end user navigates through your application.
LISTING 5-33: Working with the HiddenField server control
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub Page_Load(sender As Object, e As EventArgs)
HiddenField1.Value = Guid.NewGuid().ToString()
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>HiddenField Server Control</title>
</head>
<body>
<form id="form1" runat="server">
<asp:HiddenField ID="HiddenField1" runat="Server" />
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void Page_Load(Object sender, EventArgs e)
{
HiddenField1.Value = Guid.NewGuid().ToString();
}
</script>
In this example, the Page_Load event populates the HiddenField1 control with a GUID. You can see the hidden field and its value by looking at the source of the blank HTML page that is created. You should see a result similar to the following (the GUID will have a different value, of course):
<input type="hidden" name="HiddenField1" id="HiddenField1"
value="d447f6b9-bfbe-4eaa-859a-fb4136e95cd2" />
On the page postback, ASP.NET can detect whether the HiddenField server control has changed its value since the last post. This enables you to change the HiddenField value with client-side script and then work with the changes in a page event.
The HiddenField server control has an event called ValueChanged that you can use when the value is changed:
VB
Protected Sub HiddenField1_ValueChanged(ByVal sender As Object,
ByVal e As System.EventArgs)
' Handle event here
End Sub
C#
protected void HiddenField1_ValueChanged(object sender, EventArgs e)
{
// Handle event here
}
The ValueChanged event is triggered when the ASP.NET page is posted back to the server if the value of the HiddenField server control has changed since the last time the page was drawn. If the value has not changed, the method is never triggered. Therefore, the method is useful to act upon any changes to the HiddenField control — such as recording a value to the database or changing a value in the user’s profile.
In the very early days of ASP.NET, you could upload files using the HTML FileUpload server control. This control put an <input type="file"> element on your web page to enable the end user to upload files to the server. To use the file, however, you had to make a couple of modifications to the page. For example, you were required to add enctype="multipart/form-data" to the page’s <form> element.
Ever since ASP.NET 2.0, you have been able to use the FileUpload server control that makes the process of uploading files to a server even simpler. When giving a page the capability to upload files, you simply include the <asp:FileUpload> control, and ASP.NET takes care of the rest, including adding the enctype attribute to the page’s <form> element.
After the file is uploaded to the server, you can also take hold of the uploaded file’s properties and either display them to the end user or use these values yourself in your page’s code-behind. Listing 5-34 shows an example of using the FileUpload control. The page contains a single FileUpload control, plus a Button and a Label control.
LISTING 5-34: Uploading files using the FileUpload control
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub Button1_Click(ByVal sender As Object,
ByVal e As System.EventArgs)
If FileUpload1.HasFile Then
Try
FileUpload1.SaveAs("C:\Uploads\" &
FileUpload1.FileName)
Label1.Text = "File name: " &
FileUpload1.PostedFile.FileName & "<br>" &
"File Size: " & _
FileUpload1.PostedFile.ContentLength & " kb<br>" &
"Content type: " &
FileUpload1.PostedFile.ContentType
Catch ex As Exception
Label1.Text = "ERROR: " & ex.Message.ToString()
End Try
Else
Label1.Text = "You have not specified a file."
End If
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>FileUpload Server Control</title>
</head>
<body>
<form id="form1" runat="server">
<asp:FileUpload ID="FileUpload1" runat="server" />
<p>
<asp:Button ID="Button1" runat="server" Text="Upload"
OnClick="Button1_Click" />
</p>
<p>
<asp:Label ID="Label1" runat="server"></asp:Label>
</p>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void Button1_Click(object sender, EventArgs e)
{
if (FileUpload1.HasFile)
try
{
FileUpload1.SaveAs("C:\Uploads\" + FileUpload1.FileName);
Label1.Text = "File name: " +
FileUpload1.PostedFile.FileName + "<br>" +
FileUpload1.PostedFile.ContentLength + " kb<br>" +
"Content type: " +
FileUpload1.PostedFile.ContentType;
}
catch (Exception ex)
{
Label1.Text = "ERROR: " + ex.Message.ToString();
}
else
{
Label1.Text = "You have not specified a file.";
}
}
</script>
From this example, you can see that the entire process is rather simple. The single button on the page initiates the upload process. The FileUpload control itself does not initiate the uploading process. You must initiate it through another event such as Button_Click.
When compiling and running this page, you may notice a few things in the generated source code of the page. An example of the generated source code is presented here:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>
FileUpload Server Control
</title></head>
<body>
<form method="post" action="Listing05-34.aspx" id="form1"
enctype="multipart/form-data">
<div class="aspNetHidden">
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="YkgBQVHMwxdJnFcwbHY
G5i9hOlxcWnVeP+bjjdfpcRzkW30vLjxP75xY0wPaGlfa6YBcCAKm7gdi/7tonGDExufgpgIGwHE4yb0t6
jWepmD1DxH9i0/G69Pmr76WXQjPZcoaO7Uxyh9sbhqER1zcqg==" />
</div>
<div class="aspNetHidden">
<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION"
value="gNlwD1eVXBy2QmFixsfWZQGK7o0wSftXvY9Ff6ULdXYbqETya2cdZ5Ta2AmMcsvGIR
BNBJ3tCi8FgYsxjwfTlGGECrta3LiwFjipySbNhzhtwnY8sGfd9ygP96s9/aSE" />
</div>
<input type="file" name="FileUpload1" id="FileUpload1" />
<p>
<input type="submit" name="Button1" value="Upload" id="Button1" />
</p>
<p>
<span id="Label1"></span>
</p>
</form>
</body>
</html>
The first thing to notice is that because the FileUpload control is on the page, ASP.NET 4.5 modified the page’s <form> element on your behalf by adding the appropriate enctype attribute. Also notice that the FileUpload control was converted to an HTML <input type="file"> element.
After the file is uploaded, the first check (done in the file’s Button1_Click event handler) examines whether a file reference was actually placed within the <input type="file"> element. If a file was specified, an attempt is made to upload the referenced file to the server using the SaveAs() method of the FileUpload control. That method takes a single String parameter, which should include the location where you want to save the file. In the String parameter used in Listing 5-34, you can see that the file is being saved to a folder called Uploads, which is located in the C:\ drive.
The PostedFile.FileName attribute is used to give the saved file the same name as the file it was copied from. If you want to name the file something else, simply use the SaveAs() method in the following manner:
FileUpload1.SaveAs("C:\Uploads\UploadedFile.txt")
You could also give the file a name that specifies the time it was uploaded:
FileUpload1.SaveAs("C:\Uploads\" & System.DateTime.Now.ToFileTimeUtc() & ".txt")
After the upload is successfully completed, the Label control on the page is populated with metadata of the uploaded file. In the example, the file’s name, size, and content type are retrieved and displayed on the page for the end user. When the file is uploaded to the server, the page generated is similar to that shown in Figure 5-36.
Uploading files to another server can be an error-prone affair. It is vital to upload files in your code using proper exception handling. That is why the file in the example is uploaded using a Try Catch statement.
You might receive errors when your end users upload files to your web server through the FileUpload control in your application. Errors may occur because the destination folder on the server is not writable for the account used by ASP.NET. If ASP.NET is not enabled to write to the folder you want, you can enable it using the folder’s properties.
First, right-click on the folder where the ASP.NET files should be uploaded and select Properties from the provided menu. The Properties dialog box for the selected folder opens. Click the Security tab to make sure the IIS_IUSRS account is included in the list and has the proper permissions to write to disk. If it is enabled, you see something similar to what is presented in Figure 5-37.
If you do not see the IIS_IUSRS account in the list of users allowed to access the folder, add it by clicking the Add button and entering IIS_IUSRS in the text area provided (see Figure 5-38).
Click OK, and you can then click the appropriate check boxes to provide the permissions needed for your application.
Your end users might never encounter an issue with the file upload process in your application, but you should be aware that some limitations exist. When users work through the process of uploading files, a size restriction is actually sent to the server for uploading. The default size limitation is 4MB (4096KB); the transfer fails if a user tries to upload a file that is larger than 4096KB.
A size restriction protects your application. You want to prevent malicious users from uploading numerous large files to your web server in an attempt to tie up all the available processes on the server. Such an occurrence is called a denial of service attack. It ties up the web server’s resources so that legitimate users are denied responses from the server.
One of the great things about .NET, however, is that it usually provides a way around limitations. You can usually change the default settings that are in place. To change the limit on the allowable upload file size, you make some changes to either the root web.config file (found in the ASP.NET 4.5 configuration folder at C:\WINDOWS\Microsoft.NET\Framework\v4.0.xxxxx\CONFIG) or to your application’s web.config file.
In the web.config file, you can create a node called <httpRuntime>. In this file, you apply the settings so that the default allowable file size is dictated by the actual request size permitted to the web server (4096KB). The <httpRuntime> section of the web.config.comments file is shown in Listing 5-35.
LISTING 5-35: Changing the file size limitation setting in the web.config file
<httpRuntime
asyncPreloadMode="None"
executionTimeout="110"
maxRequestLength="4096"
requestLengthDiskThreshold="80"
useFullyQualifiedRedirectUrl="false"
minFreeThreads="8"
minLocalRequestFreeThreads="4"
appRequestQueueLimit="5000"
enableKernelOutputCache="true"
enableVersionHeader="true"
requireRootedSaveAsPath="true"
enable="true"
defaultRegexMatchTimeout="00:00:00"
shutdownTimeout="90"
delayNotificationTimeout="0"
waitChangeNotification="0"
maxWaitChangeNotification="0"
enableHeaderChecking="true"
sendCacheControlHeader="true"
apartmentThreading="false"
encoderType="System.Web.Util.HttpEncoder"
requestValidationMode="4.0"
requestValidationType="System.Web.Util.RequestValidator"
requestPathInvalidCharacters="<,>,*,%,&,:,\,?"
maxUrlLength="260"
maxQueryStringLength="2048"
relaxedUrlToFileSystemMapping="false"
allowDynamicModuleRegistration="true"
fcnMode="NotSet" />
You can do a lot with the <httpRuntime> section of the web.config file, but two properties — maxRequestLength and executionTimeout — are especially interesting.
The maxRequestLength property dictates the size of the request made to the web server. When you upload files, the file is included in the request; you alter the size allowed to be uploaded by changing the value of this property. The value presented is in kilobytes. To allow files larger than the default of 4MB, change the maxRequestLength property as follows:
maxRequestLength="10240"
This example changes the maxRequestLength property’s value to 10,240KB (10MB). With this setting in place, your end users can upload 10MB files to the server. When changing the maxRequestLength property, be aware of the setting provided for the executionTimeout property. This property sets the time (in seconds) for a request to attempt to execute to the server before ASP.NET shuts down the request (whether or not it is finished). The default setting is 90 seconds. The end user receives a timeout error notification in the browser if the time limit is exceeded. If you are going to permit larger requests, remember that they take longer to execute than smaller ones. If you increase the size of the maxRequestLength property, you should examine whether to increase the executionTimeout property as well.
Making these changes in the web.config file applies this setting to all the applications that are on the server. If you want to apply this only to the application you are working with, apply the <httpRuntime> node to the web.config file of your application, overriding any setting that is in the root web.config file. Make sure this node resides between the <system.web> nodes in the configuration file.
So far, you have seen some good examples of how to upload a file to the server without much hassle. Now, let’s look at how to upload multiple files to the server from a single page.
No built-in capabilities in the Microsoft .NET Framework enable you to upload multiple files from a single ASP.NET page. With a little work, however, you can easily accomplish this task just as you would have in the past using .NET 1.x.
The trick is to import the System.IO class into your ASP.NET page and then to use the HttpFileCollection class to capture all the files that are sent in with the Request object. This approach enables you to upload as many files as you want from a single page.
If you wanted to, you could simply handle each FileUpload control on the page individually, as shown in Listing 5-36.
LISTING 5-36: Handling each FileUpload control individually
VB
If FileUpload1.HasFile Then
' Handle this upload
End If
If FileUpload2.HasFile Then
' Handle this upload
End If
C#
if (FileUpload1.HasFile) {
/// Handle this upload
}
if (FileUpload2.HasFile) {
/// Handle this upload
}
If you are working with a limited number of file upload boxes, this approach works; but at the same time you may, in certain cases, want to handle the files using the HttpFileCollection class. This is especially true if you are working with a dynamically generated list of server controls on your ASP.NET page.
For an example of this, you can build an ASP.NET page that has three FileUpload controls and one Submit button (using the Button control). After the user clicks the Submit button and the files are posted to the server, the code-behind takes the files and saves them to a specific location on the server. After the files are saved, the file information that was posted is displayed in the ASP.NET page (see Listing 5-37).
LISTING 5-37: Uploading multiple files to the server
VB
<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub Button1_Click(ByVal sender As Object,
ByVal e As System.EventArgs)
Dim filepath As String = "C:\Uploads"
Dim uploadedFiles As HttpFileCollection = Request.Files
Dim i As Integer = 0
Do Until i = uploadedFiles.Count
Dim userPostedFile As HttpPostedFile = uploadedFiles(i)
Try
If (userPostedFile.ContentLength > 0) Then
Label1.Text += "<u>File #" & (i + 1) & "</u><br>"
Label1.Text += "File Content Type: " &
userPostedFile.ContentType & "<br>"
Label1.Text += "File Size: " &
userPostedFile.ContentLength & "kb<br>"
Label1.Text += "File Name: " &
userPostedFile.FileName & "<br>"
userPostedFile.SaveAs(filepath & "\" &
Path.GetFileName(userPostedFile.FileName))
Label1.Text += "Location where saved: " &
filepath & "\" &
Path.GetFileName(userPostedFile.FileName) &
"<p>"
End If
Catch ex As Exception
Label1.Text += "Error:<br>" & ex.Message
End Try
i += 1
Loop
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>FileUpload Server Control</title>
</head>
<body>
<form id="form1" runat="server">
<p>
<asp:FileUpload ID="FileUpload1" runat="server" />
</p>
<p>
<asp:FileUpload ID="FileUpload2" runat="server" />
</p>
<p>
<asp:FileUpload ID="FileUpload3" runat="server" />
</p>
<p>
<asp:Button ID="Button1" runat="server" Text="Upload"
OnClick="Button1_Click" />
</p>
<p>
<asp:Label ID="Label1" runat="server"></asp:Label>
</p>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<%@ Import Namespace="System.IO" %>
<!DOCTYPE html>
<script runat="server">
protected void Button1_Click(object sender, EventArgs e)
{
string filepath = "C:\Uploads";
HttpFileCollection uploadedFiles = Request.Files;
for (int i = 0; i < uploadedFiles.Count; i++)
{
HttpPostedFile userPostedFile = uploadedFiles[i];
try
{
if (userPostedFile.ContentLength > 0)
{
Label1.Text += "<u>File #" + (i + 1) +
"</u><br>";
Label1.Text += "File Content Type: " +
userPostedFile.ContentType + "<br>";
Label1.Text += "File Size: " +
userPostedFile.ContentLength + "kb<br>";
Label1.Text += "File Name: " +
userPostedFile.FileName + "<br>";
userPostedFile.SaveAs(filepath + "\" +
Path.GetFileName(userPostedFile.FileName));
Label1.Text += "Location where saved: " +
filepath + "\" +
Path.GetFileName(userPostedFile.FileName) +
"<p>";
}
}
catch (Exception Ex)
{
Label1.Text += "Error: <br>" + Ex.Message;
}
}
}
</script>
This ASP.NET page enables the end user to select up to three files and click the Upload Files button, which initializes the Button1_Click event. Using the HttpFileCollection class with the Request.Files property lets you gain control over all the files that are uploaded from the page. When the files are in this state, you can do whatever you want with them. In this case, the files’ properties are examined and written to the screen. In the end, the files are saved to the Uploads folder in the root directory of the server. The result of this action is illustrated in Figure 5-39.
One nice feature of the FileUpload control is that it not only gives you the capability to save the file to disk, but it also lets you place the contents of the file into a Stream object. You do this by using the FileContent property, as demonstrated in Listing 5-38.
LISTING 5-38: Uploading the file contents into a Stream object
VB
Dim myStream As Stream
myStream = FileUpload1.FileContent
C#
Stream myStream;
myStream = FileUpload1.FileContent;
In this short example, an instance of the Stream object is created. Then, using the FileUpload control’s FileContent property, the content of the uploaded file is placed into the object. This is possible because the FileContent property returns a Stream object.
Because you have the capability to move the file contents to a Stream object of some kind, it is also fairly simple to move the contents of the file to a Byte array (useful for such operations as placing files in a database of some kind). To do so, first move the file contents to a MemoryStream object and then convert the object to the necessary Byte array object. Listing 5-39 shows the process.
LISTING 5-39: Uploading the file contents into a Byte array
VB
Dim myByteArray() As Byte
Dim myStream As MemoryStream
myStream = FileUpload1.FileContent
myByteArray = myStream.ToArray()
C#
MemoryStream myStream;
myStream = (MemoryStream)FileUpload1.FileContent;
Byte[] myByteArray = new Byte[FileUpload1.PostedFile.ContentLength];
myByteArray = myStream.ToArray();
In this example, instances of a Byte array and a MemoryStream object are created. First, the MemoryStream object is created using the FileUpload control’s FileContent property as you did previously. Then it’s fairly simple to use the MemoryStream object’s ToArray() method to populate the myByteArray() instance. After the file is placed into a Byte array, you can work with the file contents as necessary. This is a common method to save files as an Image format for Microsoft SQL Server.
The MultiView and View server controls work together to give you the capability to turn on/off sections of an ASP.NET page. Turning sections on and off, which means activating or deactivating a series of View controls within a MultiView control, is similar to changing the visibility of Panel controls. For certain operations, however, you may find that the MultiView control is easier to manage and work with.
The sections, or views, do not change on the client-side; rather, they change with a postback to the server. You can put any number of elements and controls in each view, and the end user can work through the views based upon the sequence numbers that you assign to the views.
You can build these controls (like all server controls) from the Source view or Design view. If working with Visual Studio 2012, you can drag and drop a MultiView control onto the design surface and then drag and drop any number of View controls inside the MultiView control. Place the elements you want within the View controls. When you are finished, you have something like the view shown in Figure 5-40.
You also can create your controls directly in the code, as shown in Listing 5-40.
LISTING 5-40: Using the MultiView and View server controls
VB
<%@ Page Language="VB" %>
<script runat="server">
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
If Not Page.IsPostBack Then
MultiView1.ActiveViewIndex = 0
End If
End Sub
Sub NextView(ByVal sender As Object, ByVal e As System.EventArgs)
MultiView1.ActiveViewIndex += 1
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>MultiView Server Control</title>
</head>
<body>
<form id="form2" runat="server">
<asp:MultiView ID="MultiView1" runat="server">
<asp:View ID="View1" runat="server">
<em>Making a Great Book</em><br />
<br />
Surround yourself with talented authors.<br />
<br />
<asp:Button ID="Button1" runat="server" Text="Next Step"
OnClick="NextView" />
</asp:View>
<asp:View ID="View2" runat="server">
<em>Making a Great Book</em><br />
<br />
Write content you are passionate about.<br />
<br />
<asp:Button ID="Button2" runat="server" Text="Next Step"
OnClick="NextView" />
</asp:View>
<asp:View ID="View3" runat="server">
<em>Making a Great Book</em><br />
<br />
Have a bunch of smart technical editors review your work.<br />
<br />
<asp:Button ID="Button3" runat="server" Text="Next Step"
OnClick="NextView" />
</asp:View>
<asp:View ID="View4" runat="server">
<em>Making a Great Book</em><br />
<br />
Release the book to publishing!
</asp:View>
</asp:MultiView>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
MultiView1.ActiveViewIndex = 0;
}
}
void NextView(object sender, EventArgs e)
{
MultiView1.ActiveViewIndex += 1;
}
</script>
This example shows four views expressed in the MultiView control. Each view is constructed with an <asp:View> server control that also needs ID and Runat attributes. A button is added to each of the first three views (View1, View2, and View3) of the MultiView control. The buttons point to a server-side event that triggers the MultiView control to progress onto the next view within the series of views.
Before either of the buttons can be clicked, the MultiView control’s ActiveViewIndex attribute is assigned a value. By default, the ActiveViewIndex, which describes the view that should be showing, is set to -1. This means that no view shows when the page is generated. To start on the first view when the page is drawn, set the ActiveViewIndex property to 0, which is the first view because this is a zero-based index. Therefore, the code from Listing 5-40 first checks to see if the page is in a postback situation, and if not, the ActiveViewIndex is assigned to the first View control.
Each of the buttons in the MultiView control triggers the NextView method. NextView simply adds one to the ActiveViewIndex value, thereby showing the next view in the series until the last view is shown. The view series is illustrated in Figure 5-41.
In addition to the Next Step button on the first, second, and third views, you could place a button in the second, third, and fourth views to enable the user to navigate backward through the views. To do this, create three buttons titled Previous Step in the last three views and point them to the following method in their OnClick events:
VB
Sub PreviousView(ByVal sender As Object, ByVal e As System.EventArgs)
MultiView1.ActiveViewIndex -= 1
End Sub
C#
void PreviousView(object sender, EventArgs e)
{
MultiView1.ActiveViewIndex -= 1;
}
Here, the PreviousView method subtracts one from the ActiveViewIndex value, thereby showing the previous view in the view series.
Another option is to spice up the MultiView control by adding a step counter that displays (to a Label control) which step in the series the end user is currently performing. In the Page_PreRender event, you add the following line:
VB
Label1.Text = "Step " & (MultiView1.ActiveViewIndex + 1).ToString() &
" of " & MultiView1.Views.Count.ToString()
C#
Label1.Text = "Step " + (MultiView1.ActiveViewIndex + 1).ToString() +
" of " + MultiView1.Views.Count.ToString();
Now when working through the MultiView control, the end user sees Step 1 of 3 on the first view, which changes to Step 2 of 3 on the next view, and so on.
Much like the MultiView control, the Wizard server control enables you to build a sequence of steps that is displayed to the end user. Web pages are all about either displaying or gathering information and, in many cases, you don’t want to display all the information at once — nor do you always want to gather everything from the end user at once.
When you are constructing a step-by-step process that includes logic on the steps taken, use the Wizard control to manage the entire process. The first time you use the Wizard control, notice that it allows for a far greater degree of customization than does the MultiView control.
In its simplest form, the Wizard control can be just an <asp:Wizard> element with any number of <asp:WizardStep> elements. Listing 5-41 creates a Wizard control that works through three steps.
LISTING 5-41: A simple Wizard control
<%@ Page Language="C#" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Wizard server control</title>
</head>
<body>
<form id="form1" runat="server">
<asp:Wizard ID="Wizard1" runat="server" DisplaySideBar="True"
ActiveStepIndex="0">
<WizardSteps>
<asp:WizardStep ID="WizardStep1" runat="server" Title="Step 1">
This is the first step.
</asp:WizardStep>
<asp:WizardStep ID="WizardStep2" runat="server" Title="Step 2">
This is the second step.
</asp:WizardStep>
<asp:WizardStep ID="WizardStep3" runat="server" Title="Step 3">
This is the third and final step.
</asp:WizardStep>
</WizardSteps>
</asp:Wizard>
</form>
</body>
</html>
In this example, three steps are defined with the <asp:WizardSteps> control. Each step contains content — simply text in this case, although you can put in anything you want, such as other web server controls or even user controls. The order in which the WizardSteps are defined is based completely on the order in which they appear within the <WizardSteps> element.
The <asp:Wizard> element contains a couple of important attributes. The first is DisplaySideBar. In this example, it is set to True by default — meaning that a side navigation system in the displayed control enables the end user to quickly navigate to other steps in the process. The ActiveStepIndex attribute of the Wizard control defines the first wizard step. In this case, it is the first step — 0.
The three steps of the example Wizard control are shown in Figure 5-42.
The side navigation allows for easy access to the defined steps. The Wizard control adds appropriate buttons to the steps in the process. The first step has simply a Next button, the middle step has Previous and Next buttons, and the final step has Previous and Finish buttons. The user can navigate through the steps using either the side navigation or the buttons on each of the steps. You can customize the Wizard control in so many ways that it’s reminiscient of the other rich web server controls from ASP.NET, such as the Calendar control. Because so much is possible, only a few of the basics are covered — the ones you are most likely to employ in some of the Wizard controls you build.
The steps in the Figure 5-42 example are defined as Step 1, Step 2, and Step 3. The links are created based on the Title property’s value that you give to each of the <asp:WizardStep> elements in the Wizard control:
<asp:WizardStep ID="WizardStep1" runat="server" Title="Step 1">
This is the first step.
</asp:WizardStep>
By default, each wizard step created in Design view is titled Step X (with X being the number in the sequence). You can easily change the value of the Title attributes of each of the wizard steps to define the steps as you see fit. Figure 5-43 shows the side navigation of the Wizard control with renamed titles.
Another interesting point of customization for the side navigation piece of the Wizard control is the AllowReturn attribute. By setting this attribute on one of the wizard steps to False, you can remove the capability for end users to go back to this step after they have viewed it. The end user cannot navigate backward to any viewed steps that contain the attribute, but he would be able to return to any steps that do not contain the attribute or that have it set to True:
<asp:WizardStep ID="WizardStep1" runat="server" AlowReturn="False"
Title="The very first step">This is the first step.</asp:WizardStep>
Another interesting attribute in the <asp:WizardStep> element is StepType. The StepType attribute defines the structure of the buttons used on the steps. By default, the Wizard control places only a Next button on the first step. It understands that you do not need the Previous button there. It also knows to use a Next and Previous button on the middle step, and it uses Previous and Finish buttons on the last step. It draws the buttons in this fashion because, by default, the StepType attribute is set to Auto, meaning that the Wizard control determines the placement of buttons. You can, however, take control of the StepType attribute in the <asp:WizardStep> element to make your own determination about which buttons are used for which steps.
In addition to Auto, StepType value options include Start, Step, Finish, and Complete. Start means that the step defined has only a Next button. It simply allows the user to proceed to the next step in the series. A value of Step means that the wizard step has Next and Previous buttons. A value of Finish means that the step includes a Previous and a Finish button. Complete enables you to give some final message to the end user who is working through the steps of your Wizard control. In the Wizard control shown in Listing 5-42, for example, when the end user gets to the last step and clicks the Finish button, nothing happens and the user just stays on the last page. You can add a final step to give an ending message, as shown in Listing 5-42.
LISTING 5-42: Having a complete step in the Wizard step collection
<%@ Page Language="C#" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Wizard server control</title>
</head>
<body>
<form id="form1" runat="server">
<asp:Wizard ID="Wizard1" runat="server" DisplaySideBar="True"
ActiveStepIndex="0">
<WizardSteps>
<asp:WizardStep ID="WizardStep1" runat="server" Title="Step 1">
This is the first step.
</asp:WizardStep>
<asp:WizardStep ID="WizardStep2" runat="server" Title="Step 2">
This is the second step.
</asp:WizardStep>
<asp:WizardStep ID="WizardStep3" runat="server" Title="Step 3">
This is the third and final step.
</asp:WizardStep>
<asp:WizardStep ID="WizardStep4" runat="server" Title="Final Step"
StepType="Complete">
Thanks for working through the steps.
</asp:WizardStep>
</WizardSteps>
</asp:Wizard>
</form>
</body>
</html>
When the end user clicks the Finish button in Step 3, the last step — Final Step — is shown and no buttons appear with it.
The Wizard control enables you to place a header at the top of the control by means of the HeaderText attribute in the main <asp:Wizard> element. Listing 5-43 provides an example.
LISTING 5-43: Working with the HeaderText attribute
<asp:Wizard ID="Wizard1" runat="server" DisplaySideBar="True"
ActiveStepIndex="0" HeaderText="Step by Step with the Wizard Control"
HeaderStyle-BackColor="DarkGray" HeaderStyle-Font-Bold="true"
HeaderStyle-Font-Size="20">
. . .
</asp:Wizard>
This code creates a header that appears on each of the steps in the wizard. The result of this snippet is shown in Figure 5-44.
As stated earlier, the Wizard control allows for a very high degree of customization — especially in the area of style. You can customize every aspect of the process, as well as how every element appears to the end user.
Pay particular attention to the options that are available for customization of the navigation buttons. By default, the wizard steps use Next, Previous, and Finish buttons throughout the entire series of steps. From the main <asp:Wizard> element, you can change everything about these buttons and how they work.
First, if you look through the long list of attributes available for this element, notice that one available button is not shown by default: the Cancel button. Set the value of the DisplayCancelButton attribute to True, and a Cancel button appears within the navigation created for each step, including the final step in the series. Figure 5-45 shows a Cancel button in a step.
After you decide which buttons to use within the Wizard navigation, you can choose their style. By default, regular buttons appear; you can change the button style with the CancelButtonType, FinishStepButtonType, FinishStepPreviousButtonType, NextStepButtonType, PreviousStepButtonType, and StartStepNextButtonType attributes. If you use any of these button types and want all the buttons consistently styled, you must change each attribute to the same value. The possible values of these button-specific elements include Button, Image, and Link. Button is the default and means that the navigation system uses buttons. A value of Image enables you to use image buttons, and Link turns a selected item in the navigation system into a hyperlink.
In addition to these button-specific attributes of the <asp:Wizard> element, you can also specify a URL to which the user is directed when the user clicks the Cancel or Finish buttons. To redirect the user with one of these buttons, you use the CancelDestinationPageUrl or the FinishDestinationPageUrl attributes and set the appropriate URL as the destination.
Finally, you are not required to use the default text included with the buttons in the navigation system. You can change the text of each of the buttons using the CancelButtonText, FinishStepButtonText, FinishStepPreviousButtonText, NextStepButtonText, PreviousStepButtonText, and StartStepNextButtonText attributes.
One of the most convenient capabilities of the Wizard control is that it enables you to divide large forms into logical pieces. The end user can then work systematically through each section of the form. The developer, dealing with the inputted values of the form, has a few options because of the various events that are available in the Wizard control.
The Wizard control exposes events for each of the possible steps that an end user might take when working with the control. Table 5-2 describes each of the available events.
EVENT | DESCRIPTION |
ActiveStepChanged | Triggers when the end user moves from one step to the next. It does not matter if the step is the middle or final step in the series. This event simply covers each step change generically. |
CancelButtonClick | Triggers when the end user clicks the Cancel button in the navigation system. |
FinishButtonClick | Triggers when the end user clicks the Finish button in the navigation system. |
NextButtonClick | Triggers when the end user clicks the Next button in the navigation system. |
PreviousButtonClick | Triggers when the end user clicks the Previous button in the navigation system. |
SideBarButtonClick | Triggers when the end user clicks one of the links contained within the sidebar navigation of the Wizard control. |
By working with these events, you can create a multi-step form that saves all the end user’s input information when he changes from one step to the next. You can also use the FinishButtonClick event to save everything that was stored in each of the steps at the end of the process. The Wizard control remembers all the end user’s input in each of the steps by means of the view state in the page, which enables you to work with all these values in the last step. It also gives the end user the capability to go back to previous steps and change values before those values are saved to a data store.
The event appears in your code-behind or inline code, as shown in Listing 5-44.
LISTING 5-44: The FinishButtonClick event
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub Wizard1_FinishButtonClick(sender As Object,
e As WizardNavigationEventArgs)
. . .
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Wizard server control</title>
</head>
<body>
<form id="form1" runat="server">
<asp:Wizard ID="Wizard1" runat="server" DisplaySideBar="True"
ActiveStepIndex="0" OnFinishButtonClick="Wizard1_FinishButtonClick">
<WizardSteps>
<asp:WizardStep ID="WizardStep1" runat="server" Title="Step 1">
This is the first step.
</asp:WizardStep>
<asp:WizardStep ID="WizardStep2" runat="server" Title="Step 2">
This is the second step.
</asp:WizardStep>
<asp:WizardStep ID="WizardStep3" runat="server" Title="Step 3">
This is the third and final step.
</asp:WizardStep>
</WizardSteps>
</asp:Wizard>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void Wizard1_FinishButtonClick(object sender,
WizardNavigationEventArgs e)
{
. . .
}
</script>
The OnFinishButtonClick attribute should be added to the main <asp:Wizard> element to point at the Wizard1_FinishButtonClick event. Listing 5-45 shows how to do this.
LISTING 5-45: The <asp:Wizard> element changes
<asp:Wizard ID="Wizard1" runat="server" DisplaySideBar="True"
ActiveStepIndex="0" OnFinishButtonClick="Wizard1_FinishButtonClick">
The Wizard control is one of the great controls that enable you to break up longer workflows into more manageable pieces for your end users. By separating longer Web Forms into various wizard steps, you can effectively make your forms easy to understand and less daunting to the end user.
So far, you have learned how to work with each of the Wizard control steps, including how to add steps to the process and how to work with the styling of the control. Now look at how you put form elements into the Wizard control to collect information from the end user in a stepped process. This is just as simple as the first examples of the Wizard control that used only text in each of the steps.
One nice thing about putting form elements in the Wizard step process is that the Wizard control remembers each input into the form elements from step to step, enabling you to save the results of the entire form at the last step. It also means that when the end user presses the Previous button, the data that is entered into the form previously is still there and can be changed.
Listing 5-46 shows the first part of a process that steps through entering form information by building a registration process. The last step of the process saves the results to a database of your choice, although in this example, you just push the results to a Label control on the page.
LISTING 5-46: Building the form in the Wizard control
<asp:Wizard ID="Wizard1" runat="Server">
<WizardSteps>
<asp:WizardStep ID="WizardStep1" runat="server"
Title="Provide Personal Info">
First name:<br />
<asp:TextBox ID="fnameTextBox" runat="server"></asp:TextBox><br />
Last name:<br />
<asp:TextBox ID="lnameTextBox" runat="server"></asp:TextBox><br />
Email:<br />
<asp:TextBox ID="emailTextBox" runat="server"></asp:TextBox><br />
</asp:WizardStep>
<asp:WizardStep ID="WizardStep2" runat="server"
Title="Membership Information">
Are you already a member of our group?<br />
<asp:RadioButton ID="RadioButton1" runat="server" Text="Yes"
GroupName="Member" />
<asp:RadioButton ID="RadioButton2" runat="server" Text="No"
GroupName="Member" />
</asp:WizardStep>
<asp:WizardStep ID="WizardStep3" runat="server"
Title="Provided Information"
StepType="Complete" OnActivate="WizardStep3_Activate">
<asp:Label ID="Label1" runat="server" />
</asp:WizardStep>
</WizardSteps>
</asp:Wizard>
This Wizard control has three steps. The first step asks for the user’s personal information, and the second asks for the user’s membership information. The third step contains a Label control that pushes out all the information that was input. This is done through the Activate event that is specific for the WizardStep object on the third WizardStep control. The code for the WizardStep3_Activate event is shown in Listing 5-47.
LISTING 5-47: Adding an Activate event to a WizardStep object
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub WizardStep3_Activate(ByVal sender As Object,
ByVal e As System.EventArgs)
' You could save the inputted data to the database here instead
Label1.Text = "First name: " & fnameTextBox.Text.ToString() & "<br>" & _
"Last name: " & lnameTextBox.Text.ToString() & "<br>" &
"Email: " & emailTextBox.Text.ToString()
End Sub
</script>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void WizardStep3_Activate(object sender, EventArgs e)
{
Label1.Text = "First name: " + fnameTextBox.Text.ToString() + "<br>" +
"Last name: " + lnameTextBox.Text.ToString() + "<br>" +
"Email: " + emailTextBox.Text.ToString();
}
</script>
When the end user comes to the third step in the display, the WizardStep3_Activate method from Listing 5-47 is invoked. Using the OnActivate attribute in the third WizardStep control, the content provided by the end user in earlier steps is used to populate a Label control. The three steps are shown in Figure 5-46.
This example is simple and straightforward, but you can increase the complexity a little bit. Imagine you want to add another WizardStep control to the process, and you want to display it only if a user specifies that he is a member in WizardStep2. If he answers from the radio button selection that he is not a member, you have him skip the new step and go straight to the final step where the results are displayed in the Label control. First, add a WizardStep to the Wizard control, as shown in Listing 5-48.
LISTING 5-48: Adding a WizardStep
<asp:Wizard ID="Wizard1" runat="Server">
<WizardSteps>
<asp:WizardStep ID="WizardStep1" runat="server"
Title="Provide Personal Info">
First name:<br />
<asp:TextBox ID="fnameTextBox" runat="server"></asp:TextBox><br />
Last name:<br />
<asp:TextBox ID="lnameTextBox" runat="server"></asp:TextBox><br />
Email:<br />
<asp:TextBox ID="emailTextBox" runat="server"></asp:TextBox><br />
</asp:WizardStep>
<asp:WizardStep ID="WizardStep2" runat="server"
Title="Membership Information">
Are you already a member of our group?<br />
<asp:RadioButton ID="RadioButton1" runat="server" Text="Yes"
GroupName="Member" />
<asp:RadioButton ID="RadioButton2" runat="server" Text="No"
GroupName="Member" />
</asp:WizardStep>
<asp:WizardStep ID="MemberStep" runat="server"
Title="Provide Membership Number">
Membership Number:<br />
<asp:TextBox ID="mNumberTextBox" runat="server"></asp:TextBox>
</asp:WizardStep>
<asp:WizardStep ID="WizardStep3" runat="server"
Title="Provided Information"
StepType="Complete" OnActivate="WizardStep3_Activate">
<asp:Label ID="Label1" runat="server" />
</asp:WizardStep>
</WizardSteps>
</asp:Wizard>
A single step was added to the workflow — one that simply asks the member for his or her membership number. Since you want to show this step only if the end user specifies that he or she is a member in WizardStep2, you add an event (shown in Listing 5-49) designed to check for that specification.
LISTING 5-49: Applying logical checks on whether to show a step
VB
Sub Wizard1_NextButtonClick(ByVal sender As Object,
ByVal e As System.Web.UI.WebControls.WizardNavigationEventArgs)
If e.NextStepIndex = 2 Then
If RadioButton1.Checked = True Then
Wizard1.ActiveStepIndex = 2
Else
Wizard1.ActiveStepIndex = 3
End If
End If
End Sub
C#
void Wizard1_NextButtonClick(object sender, WizardNavigationEventArgs e)
{
if (e.NextStepIndex == 2)
{
if (RadioButton1.Checked == true)
{
Wizard1.ActiveStepIndex = 2;
}
else
{
Wizard1.ActiveStepIndex = 3;
}
}
}
To check whether you should show a specific step in the process, use the NextButtonClick event from the Wizard control. The event uses the WizardNavigationEventArgs class instead of the typical EventArgs class that gives you access to the NextStepIndex number, as well as to the CurrentStepIndex number.
In the example from Listing 5-49, you check whether the next step to be presented in the process is 2. Remember that this is index 2 from a zero-based index (0, 1, 2, and so on). If it is Step 2 in the index, you check which radio button is selected from the previous WizardStep. If the RadioButton1 control is checked (meaning that the user is a member), the next step in the process is assigned as index 2. If the RadioButton2 control is selected, the user is not a member, and the index is then assigned as 3 (the final step), thereby bypassing the membership step in the process.
You could also take this example and alter it a bit so that you show a WizardStep only if the user is contained within a specific role (such as an Admin role).
Showing only a WizardStep when the user is contained within a certain role is demonstrated in Listing 5-50.
LISTING 5-50: Applying logical checks on whether to show a step based upon roles
VB
Sub Wizard1_NextButtonClick(ByVal sender As Object,
ByVal e As System.Web.UI.WebControls.WizardNavigationEventArgs)
If e.NextStepIndex = 2 Then
If (Roles.IsUserInRole("ManagerAccess")) Then
Wizard1.ActiveStepIndex = 2
Else
Wizard1.ActiveStepIndex = 3
End If
End If
End Sub
C#
void Wizard1_NextButtonClick(object sender, WizardNavigationEventArgs e)
{
if (e.NextStepIndex == 2)
{
if (Roles.IsUserInRole("ManagerAccess"))
{
Wizard1.ActiveStepIndex = 2;
}
else
{
Wizard1.ActiveStepIndex = 3;
}
}
}
The ImageMap server control enables you to turn an image into a navigation menu. In the past, many developers would break an image into multiple pieces and put it together again in a table, reassembling the pieces into one image. When the end user clicked a particular piece of the overall image, the application picked out which piece of the image was chosen and based actions upon that particular selection.
With the ImageMap control, you can take a single image and specify particular hotspots on the image using coordinates. An example is shown in Listing 5-51.
LISTING 5-51: Specifying sections of an image that are clickable
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub ImageMap1_Click(sender As Object, e As ImageMapEventArgs)
Response.Write("You selected: " & e.PostBackValue)
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>ImageMap Control</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ImageMap ID="ImageMap1" runat="server" HotSpotMode="PostBack"
ImageUrl="~/Images/kids.jpg" OnClick="ImageMap1_Click">
<asp:CircleHotSpot PostBackValue="Addison" Radius="26" X="145"
Y="372" />
<asp:CircleHotSpot PostBackValue="Brayden" Radius="20" X="181"
Y="314" />
<asp:CircleHotSpot PostBackValue="Arianna" Radius="28" X="245"
Y="344" />
</asp:ImageMap>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void ImageMap1_Click(object sender, ImageMapEventArgs e)
{
Response.Write("You selected: " + e.PostBackValue);
}
</script>
This page brings up an image of me and my children at an aquarium. If you click one of the children’s faces, the child’s name will be written to the Response stream, as shown in Figure 5-47.
The ImageMap control enables you to specify hotspots in a couple of different ways. From the example in Listing 5-51, you can see that hotspots are placed in a circular fashion using the <asp:CircleHotSpot> element. Besides the <asp:CircleHotSpot> control, you can also use the <asp:RectangleHotSpot> and the <asp:PolygonHotSpot> controls. Each control takes coordinates appropriate to its shape.
After you define the hotspots on the image, you can respond to the end user click of the hotspot in several ways. You first specify how to deal with the hotspot clicks in the root <asp:ImageMap> element with the use of the HotSpotMode attribute.
The HotSpotMode attribute can take the values PostBack, Navigate, or InActive. In the previous example, the HotSpotMode value is set to PostBack — meaning that after the end user clicks the hotspot, you want to postback to the server and deal with the click at that point.
Because the HotSpotMode is set to PostBack and you have created several hotspots, you must determine which hotspot is selected. You make this determination by giving each hotspot (<asp:CircleHotSpot>) a postback value with the PostBackValue attribute. The example uses Arianna, Addison, and Brayden as the values of the three hotspots.
The PostBackValue attribute is also the helper text that appears in the browser (in the yellow box) directly below the mouse cursor when the end user hovers the mouse over the hotspot.
After the user clicks one of the hotspots, the event procedure displays the value that was selected in a Response.Write statement.
Instead of posting back to the server, you can also navigate to an entirely different URL when a particular hotspot is selected. To accomplish this, change the HotSpotMode attribute in the main <asp:ImageMap> element to the value Navigate. Then, within the <asp:CircleHotSpot> elements, simply use the NavigateUrl attribute and assign the location to which the end user should be directed if that particular hotspot is clicked:
<asp:ImageMap ID="ImageMap1" runat="server" ImageUrl="~/Images/kids.jpg"
HotSpotMode="Navigate">
<asp:CircleHotSpot AlternateText="Addison" NavigateUrl="Addison.aspx"
Radius="26" X="145" Y="372" />
<asp:CircleHotSpot AlternateText="Brayden" NavigateUrl="Brayden.aspx"
Radius="20" X="181" Y="314" />
<asp:CircleHotSpot AlternateText="Arianna" NavigateUrl="Arianna.aspx"
Radius="28" X="245" Y="344" />
</asp:ImageMap>
This chapter explored numerous server controls, their capabilities, and the features they provide. With ASP.NET 4.5, you have more than 50 server controls at your disposal.
Because you have so many server controls at your disposal when you are creating your ASP.NET applications, you have to think carefully about which is the best control for the task. Many controls seem similar, but they offer different features. These controls guarantee that you can build the best possible applications for all browsers.
Server controls are some of the most useful tools you will find in your ASP.NET arsenal. They are quite useful and can save you a lot of time. This chapter introduced you to some of these controls and to the different ways you might incorporate them into your next projects. All these controls are wonderful options to use on any of your ASP.NET pages and make it much easier to develop the functionality that your pages require.