Imagine that you are creating a form with an optional section. For example, imagine that you are creating an online tax form, and you want to display or hide a section that contains questions that apply only to married tax filers. Or, imagine that you want to add an additional help button to the tax form. You might want to hide or display detailed instructions for completing form questions depending on a user 's preferences. Finally, imagine that you want to break the tax form into multiple pages so that a person views only one part of the tax form at a time. In the following sections, you learn about the properties that you can use to hide and display controls in a form. You learn how to use the Visible and Enabled properties with individual controls and groups of controls to hide and display page content. Using the Visible and Enabled PropertiesEvery control, including both HTML and Web controls, has a Visible property that determines whether the control is rendered. When a control's Visible property has the value False , the control is not displayed on the page; the control is not processed for either pre-rendering or rendering. Web controls (but not every HTML control) have an additional property named Enabled . When Enabled has the value False and you are using Internet Explorer version 4.0 or higher, the control appears ghosted and no longer functions. When used with other browsers, such as Netscape Navigator, the control might not appear ghosted , but it does not function. The page in Listing 4.5 illustrates how both the Visible and Enabled properties affect the appearance of controls. See Figure 4.1 for the output of the page on Internet Explorer 5.5. Listing 4.5 Display.aspx<Script Runat="Server"> Sub lbtnVisible_Click( s As Object, e As EventArgs ) If txtTextBox.Visible = True Then txtTextBox.Visible = False lnkHyperLink.Visible = False lbtnLinkButton.Visible = False btnButton.Visible = False lbtnVisible.Text = "Make Visible!" Else txtTextBox.Visible = True lnkHyperLink.Visible = True lbtnLinkButton.Visible = True btnButton.Visible = True lbtnVisible.Text = "Make Invisible!" End If End Sub Sub lbtnEnabled_Click( s As Object, e As EventArgs ) If txtTextBox.Enabled = True Then txtTextBox.Enabled = False lnkHyperLink.Enabled = False lbtnLinkButton.Enabled = False btnButton.Enabled = False lbtnEnabled.Text = "Make Enabled!" Else txtTextBox.Enabled = True lnkHyperLink.Enabled = True lbtnLinkButton.Enabled = True btnButton.Enabled = True lbtnEnabled.Text = "Make Disabled!" End If End Sub </Script> <html> <head><title>Display.aspx</title></head> <body> <form Runat="Server"> TextBox: <br> <asp:TextBox ID="txtTextBox" Text="Some Text" Runat="Server" /> <p> HyperLink: <br> <asp:HyperLink ID="lnkHyperLink" NavigateURL="somepage.aspx" Text="Click Here!" Runat="Server" /> <p> LinkButton: <br> <asp:LinkButton ID="lbtnLinkButton" Text="Click Here!" Runat="Server" /> <p> Button: <br> <asp:Button ID="btnButton" Text="Submit!" Runat="Server" /> <hr> <asp:LinkButton ID="lbtnVisible" Text="Make Invisible!" OnClick="lbtnVisible_Click" Runat="Server" /> <asp:LinkButton ID="lbtnEnabled" Text="Make Disabled!" OnClick="lbtnEnabled_Click" Runat="Server" /> </form> </body> </html> The C# version of this code can be found on the CD-ROM. Figure 4.1. The Visible and Enabled properties.
The page in Listing 4.5 contains two LinkButton controls initially labeled Make Invisible! and Make Disabled! If you click the Make Invisible! link, the Visible property of all the controls is set to False . All the controls disappear from the page when the page is rendered. Clicking the Make Disabled! link has different effects when used with different browsers. When you use this link with Internet Explorer, you cannot enter any text into form controls that have been disabled. Furthermore, the Button control appears ghosted, and it no longer can be clicked. NOTE Exactly how the Enabled property affects the rendering of a form control depends on how a browser interprets the HTML Disabled attribute, which is part of the HTML 4.0 standard (see http://www.w3.org/TR/html4/). According to the standard, it should apply to all the standard HTML form tags. When used with Netscape Navigator, on the other hand, the Disabled property has no effect on the appearance of any form elements. In particular, you can still click the form button and the form will be submitted. Regardless of the browser you use, the Disabled property never has an effect on the function of the HyperLink control. If you disable a hyperlink, you can still click it and navigate to a page (Internet Explorer version 6.0 and higher displays a ghosted hyperlink in gray, but it still functions). Finally, the Disabled property always modifies the appearance of a link button. When a link button is disabled on either Microsoft Internet Explorer or Netscape Navigator, the LinkButton control is rendered as text and not as a HyperText link. Using the Panel ControlInstead of setting the Visible property for controls one by one, you can use the Panel control to hide controls as a group . All the properties of this control are listed in Table 4.1. Table 4.1. Panel Properties, Methods , and Events
Suppose that you have a form that contains a RadioButtonList control that enables users to pick their favorite Web site. Now, imagine that one option on the list is labeled Other Site . If someone picks Other Site , you want to display a text box that enables the person to enter the name of the new Web site. You can hide and display a group of controls by using the Panel control. The page in Listing 4.6 demonstrates how you can set the Visible property of a Panel control to display and hide a text box when the Other Site option is selected (see Figure 4.2). Listing 4.6 Panel.aspx<Script Runat="Server"> Sub Button_Click( s As Object, e As EventArgs ) If dropFavSite.SelectedIndex = 3 Then pnlOtherSite.Visible = True Else pnlOtherSite.Visible = False End If End Sub </Script> <html> <head><title>Panel.aspx</title></head> <body> <form Runat="Server"> Select your favorite ASP Web site: <br> <asp:RadioButtonList ID="dropFavSite" Runat="Server"> <asp:ListItem Text="Superexpert" /> <asp:ListItem Text="LearnASP" /> <asp:ListItem Text="DotNetJunkies" /> <asp:ListItem Text="Other Site" /> </asp:RadioButtonList> <asp:Panel ID="pnlOtherSite" Visible="False" Runat="Server"> <p> Other Site: <br> <asp:TextBox ID="txtOtherSite" Runat="Server" /> </asp:Panel> <p> <asp:Button Text="Submit!" OnClick="Button_Click" Runat="Server" /> </form> </body> </html> The C# version of this code can be found on the CD-ROM. Figure 4.2. Hiding and displaying content with the Panel control.
The Panel control acts as a container for other controls. Hiding a panel by setting its Visible property to False also hides all the controls that the panel contains. Simulating Multipage FormsImagine that you have a form, which contains 50 questions that you want to break up into multiple pages. One way to do so would be to actually create a separate ASP.NET page for each group of questions. Creating a form that spans multiple ASP.NET pages, however, would take a lot of work. You would need some method of storing the answers that a user entered for page 1 when the user is on page 5. You could use hidden form fields or Session variables , but there is an easier way. Instead of breaking the form into multiple ASP.NET pages, you can place all the questions within a single ASP.NET page. You can use the Panel control to display and hide different sections of the form at a time. The advantage of this approach is that all the answers entered into the form are automatically preserved. When the Panel control displays the questions for page 5, the answers to the questions for page 1 are still safely tucked away in an invisible panel. The page in Listing 4.7 demonstrates how you would use this method to create a simulated three-page form. Listing 4.7 PanelMultiPage.aspx<Script Runat="Server"> Sub Page_Load If Not IsPostBack Then ViewState( "CurrentPage" ) = 1 End If End Sub Sub btnNextPage_Click( s As Object, e As EventArgs ) Dim pnlPanel As Panel Dim strPanelName AS String ' Hide Previous Panel strPanelName = "pnlForm" & ViewState( "CurrentPage" ) pnlPanel = FindControl( strPanelName ) pnlPanel.Visible = False ' Show Current Panel ViewState( "CurrentPage" ) += 1 strPanelName = "pnlForm" & ViewState( "CurrentPage" ) pnlPanel = FindControl( strPanelName ) pnlPanel.Visible = True End Sub Sub btnPrevPage_Click( s As Object, e As EventArgs ) Dim pnlPanel As Panel Dim strPanelName AS String ' Hide Current Panel strPanelName = "pnlForm" & ViewState( "CurrentPage" ) pnlPanel = FindControl( strPanelName ) pnlPanel.Visible = False ' Show Previous Panel ViewState( "CurrentPage" ) -= 1 strPanelName = "pnlForm" & ViewState( "CurrentPage" ) pnlPanel = FindControl( strPanelName ) pnlPanel.Visible = True End Sub Sub btnFinish_Click( s As Object, e As EventArgs ) pnlForm3.Visible = False pnlForm4.Visible = True lblSummary.Text = "<h2>You entered:</h2>" lblSummary.Text &= "<li> First Name=" & txtFirstname.Text lblSummary.Text &= "<li> Last Name=" & txtLastname.Text lblSummary.Text &= "<li> Color=" & txtFavColor.Text lblSummary.Text &= "<li> Philosopher=" & radlFavPhilosopher.SelectedItem.Text End Sub </Script> <html> <head><title>PanelMultiPage.aspx</title></head> <body> <form Runat="Server"> <asp:Panel ID="pnlForm1" Runat="Server"> <h3>Page <%=ViewState( "CurrentPage" )%> of 3</h3> <hr> First Name: <asp:TextBox ID="txtFirstname" Runat="Server" /> <p> Last Name: <asp:TextBox ID="txtLastname" Runat="Server" /> <hr> <asp:Button Text="Next Page >>" OnClick="btnNextPage_Click" Runat="Server" /> </asp:Panel> <asp:Panel ID="pnlForm2" Runat="Server" Visible="False"> <h3>Page <%=ViewState( "CurrentPage" )%> of 3</h3> <hr> Favorite Color: <asp:TextBox ID="txtfavColor" Runat="Server" /> <hr> <asp:Button Text="<< Prev Page" OnClick="btnPrevPage_Click" Runat="Server" /> <asp:Button Text="Next Page >>" OnClick="btnNextPage_Click" Runat="Server" /> </asp:Panel> <asp:Panel ID="pnlForm3" Runat="Server" Visible="False"> <h3>Page <%=ViewState( "CurrentPage" )%> of 3</h3> <hr> Favorite Philosopher: <asp:RadioButtonList ID="radlFavPhilosopher" Runat="Server"> <asp:ListItem Text="Frege" Selected="True"/> <asp:ListItem Text="Russell" /> <asp:ListItem Text="Carnap" /> </asp:RadioButtonList> <hr> <asp:Button Text="<< Prev Page" OnClick="btnPrevPage_Click" Runat="Server" /> <asp:Button Text="Finish" OnClick="btnFinish_Click" Runat="Server" /> </asp:Panel> <asp:Panel ID="pnlForm4" Runat="Server" Visible="False"> <asp:Label ID="lblSummary" Runat="Server"/> </asp:Panel> </form> </body> </html> The C# version of this code can be found on the CD-ROM. The page in Listing 4.7 contains four Panel controls (see Figure 4.3). Each of the first three Panel controls contains a group of form questions. The final Panel control displays a summary of the information that the user entered. Figure 4.3. Simulating multipage forms with the Panel control.
When the Next Page button is clicked, the btnNextPage_Click subroutine is executed. This subroutine hides the previous panel and displays the contents of the next panel. The Previous Page button causes the opposite operation to take place. When the Previous Page button is clicked, the current panel is hidden and the contents of the previous panel are displayed. Finally, if you click the Finish button, all the Panel controls are hidden except for the fourth panel, which displays a summary of all the values the user entered into the form fields in the previous panels. Adding Controls ProgrammaticallyAn ASP.NET page is built from controls. Every element of a page, including the static text and HTML content, is represented by a control. You can retrieve a list of the controls contained in a page by using the Controls property of the Page class. For example, the following code loops through the Controls collection and displays each of its members : Dim ctlControl As Control For Each ctlControl in Page.Controls Response.Write( ctlControl.ToString() ) Next The preceding code does not display a list of all the controls contained in a page. It displays only the immediate child controls of the Page class; it does not display any child controls of these controls. The HTMLForm control, for example, contains child controls. It contains all the form controls on a page. The Panel control is another example of a control that contains child controls. Every control has a Controls property that represents its child controls. If you want to display all the controls in a page, you can move recursively through the Controls collection of each control, as in Listing 4.8. Listing 4.8 Controls.aspx<Script Runat="Server"> Dim strControlList As String Sub Page_Load strControlList = "<ul>" DisplayControls( Page ) strcontrolList &= "</ul>" lblOutput.Text = strControlList End Sub Sub DisplayControls( s As Object ) Dim ctlControl As Control For Each ctlControl in s.Controls DisplayControlInfo( ctlControl ) strControlList &= "<ul>" DisplayControls( ctlControl ) strControlList &= "</ul>" Next End Sub Sub DisplayControlInfo( s As Object ) strControlList &= "<li> Client ID: " & s.ClientID strControlList &= "<br> Type: " & s.GetType().ToString() strControlList &= "<br> ID: " & s.ID strControlList &= "<br> Naming Container: " & s.NamingContainer.ToString() strControlList &= "<br> Page: " & s.Page.ToString() strControlList &= "<br> Parent: " & s.Parent.ToString() strControlList &= "<br> Unique ID: " & s.UniqueID strControlList &= "<p>" End Sub </Script> <html> <head><title>Controls.aspx</title></head> <body> <form Runat="Server"> <asp:Panel ID="pnlPanel" Runat="Server"> <asp:Label id="lblNewLabel" Runat="Server"/> </asp:Panel> Username: <br> <asp:TextBox ID="txtUsername" Runat="Server" /> <p> <asp:Button ID="btnButton" Text="Submit Name!" Runat="Server" /> <hr> <asp:Label ID="lblOutput" Runat="Server" /> </form> </body> </html> The C# version of this code can be found on the CD-ROM. The Page_Load subroutine in Listing 4.8 calls a subroutine named DisplayControls . This subroutine recursively displays all the controls on the page (see Figure 4.4). Figure 4.4. Recursively displaying all the controls on a page.
The values of all the properties listed in Table 4.2 is displayed for each control:
Adding Controls to a PageYou can add new controls to a page by adding the controls to a page's Controls collection. You can add a control at the end of the Controls collection by using the Add() method. Alternatively, you can add a control at a specific index location in the Controls collection by using the AddAt() method. The page in Listing 4.9, for example, constructs all its own controls. It contains a single Page_Load subroutine, which adds 30 LiteralControl controls to the page. If you open this page in your Web browser, you see the word Hello! repeated 30 times (see Figure 4.5). Listing 4.9 ControlsAdd.aspx<Script Runat="Server"> Sub Page_Load Dim intCounter As Integer For intCounter = 1 To 30 Controls.Add( New LiteralControl( "Hello!" ) ) Next End Sub </Script> The C# version of this code can be found on the CD-ROM. Figure 4.5. Self-building page.
You can remove controls from the Controls collection by using the Remove() , RemoveAt() , or Clear() method. The Remove() method removes the control that you pass to it, the RemoveAt() method removes a control at a specific index location, and the Clear() method removes all the controls from the Controls collection. The page in Listing 4.10, for example, adds three controls and then uses the Remove() method to remove the first control. Listing 4.10 ControlsRemove.aspx<Script Runat="Server"> Sub Page_Load Dim intCounter As Integer For intCounter = 1 To 3 Controls.Add( new LiteralControl( "Control" & intCounter ) ) Next Controls.Remove( Controls.Item( 0 ) ) End Sub </Script> The C# version of this code can be found on the CD-ROM. The PlaceHolder ControlTypically, you don't add controls directly to a page's Controls collection. In most cases, you will want to add a control to a particular location on a page. You can add a control to the Controls collection of any other control. For example, there is nothing wrong with adding a new control to the Controls collection of either an HTMLForm or Panel control. However, there is a special control included in the ASP.NET Framework, called the PlaceHolder control that has the singular purpose of acting as a container for other controls. Listing 4.11 illustrates how you can use the PlaceHolder control to dynamically add TextBox controls to a form. Listing 4.11 PlaceHolder.aspx<Script Runat="Server"> Sub Page_Load Dim intCounter As Integer Dim btnNewButton As Button For intCounter = 1 to 10 plhPlaceHolder.Controls.Add( _ New LiteralControl( "<p>Field " & intCounter & ": " ) ) plhPlaceHolder.Controls.Add( _ New TextBox ) Next btnNewButton = New Button btnNewButton.Text = "Click Here!" plhPlaceHolder.Controls.Add( btnNewButton ) End Sub </Script> <html> <head><title>PlaceHolder.aspx</title></html> <body> <form Runat="Server"> <asp:PlaceHolder id="plhPlaceHolder" Runat="Server" /> </form> </body> </html> The C# version of this code can be found on the CD-ROM. In the Page_Load subroutine in Listing 4.11, ten TextBox controls and one Button control are added to the Controls collection of a PlaceHolder control. When the page is displayed in a browser, the new TextBox controls are rendered. Dynamically Generating FormsImagine that you need to create a form that has a variable number of input fields. For example, you can imagine a simple order entry form that enables you to enter a variable number of product orders. The same form enables you to submit a single order or 25 orders at a time. You can use the methods discussed in the previous section to dynamically add form fields to a form. Listing 4.12 contains a simple order entry form. When the page first loads, it contains a single form field for the customer name and a single form field for the product. The page also contains a button labeled Add Product Field. When you click this button, a new product form field is added to the form. You can click this button as many times as you wish to add any number of new product form fields (see Figure 4.6). Figure 4.6. Dynamically generated form.
When you click the Add Product Field button, the AddProductFieldCount subroutine is executed. This subroutine increments the count of product fields (stored in the state bag) by one. It also adds a new text box to the page by calling the AddProductField subroutine. Notice that the Page_Load subroutine rebuilds all the product fields every time the page is loaded. When you dynamically add a new control to a page, the control is not automatically retained between form posts. The control itself is not preserved in the page's view state. However, any text you enter into a dynamically generated form field is automatically preserved in view state. Listing 4.12 DynamicForm.aspx<Script Runat="Server"> Sub Page_Load Dim intCounter As Integer If Not IsPostBack Then ViewState( "ProductFieldCount" ) = 1 ElseIf ViewState( "ProductFieldCount" ) > 1 Then For intCounter = 2 To ViewState( "ProductFieldCount" ) AddProductField( intCounter ) Next End If End Sub Sub AddProductFieldCount( s As Object, e As EventArgs ) ViewState( "ProductFieldCount" ) += 1 AddProductField( ViewState( "ProductFieldCount" ) ) End Sub Sub AddProductField( strFieldNum As String ) Dim litLabel As LiteralControl Dim txtTextBox As TextBox ' Add Literal Control litLabel = New LiteralControl litLabel.Text = "<p><b>Product " & strFieldNum & ":</b> " plhProductFields.Controls.Add( litLabel ) ' Add TextBox Control txtTextBox = New TextBox txtTextBox.ID = "txtProduct" & strFieldNum plhProductFields.Controls.Add( txtTextBox ) End Sub Sub btnSubmit_Click( s As Object, e As EventArgs ) Response.Redirect( "ThankYou.aspx" ) End Sub </Script> <html> <head><title>DynamicForm.aspx</title></html> <body> <form Runat="Server"> <b>Customer Name:</b> <asp:TextBox ID="txtCustomer" Runat="Server" /> <p> <div style="background-color: yellow;padding:10px"> <b>Product 1:</b> <asp:TextBox ID="txtProduct1" Runat="Server" /> <asp:PlaceHolder id="plhProductFields" Runat="Server" /> </div> <p> <asp:Button Text="Add Product Field" OnClick="AddProductFieldCount" Runat="Server" /> <asp:Button id="btnSubmit" Text="Submit Complete Order" OnClick="btnSubmit_Click" Runat="Server" /> </form> </body> </html> The C# version of this code can be found on the CD-ROM. Dynamically Generating List ItemsThe various list controls, such as RadioButtonList , CheckBoxList , DropDownList , and ListBox , discussed in Chapter 2, "Building Forms with Web Server Controls," present a special case. You can dynamically add and remove items from these controls by working with the properties and methods of the ListItemCollection collection. The properties and methods of the ListItemCollection collection are described in Table 4.2. Table 4.2. ListItemCollection Collection Properties and Methods
You can use the properties and methods of the list controls to create complex interactions between the elements of a form. For example, the page contained in Listing 4.13 contains two ListBox controls: one labeled Products and one labeled Shopping Cart . When you click an item listed in the Products list box, the item is automatically added to the Shopping Cart list box (see Figure 4.7). Figure 4.7. Manipulating the ListItem collection.
The Shopping Cart list box has Remove Item and Remove All buttons . Clicking Remove Item removes the selected item from the Shopping Cart list box, and clicking Remove All removes all the items from the list box. Listing 4.13 ListItemCollection.aspx<Script Runat="Server"> Sub lstProducts_SelectedIndexChanged( s As Object, e As EventArgs ) lstCart.SelectedIndex = -1 lstCart.Items.Add( lstProducts.SelectedItem ) End Sub Sub btnRemove_Click( s As Object, e As EventArgs ) lstCart.Items.Remove( lstCart.SelectedItem ) End Sub Sub btnRemoveAll_Click( s As Object, e As EventArgs ) lstCart.Items.Clear() End Sub </Script> <html> <head><title>ListItemCollection.aspx</title></head> <body> <form Runat="Server"> <h2>Products:</h2> <asp:ListBox id="lstProducts" Width="200" AutoPostBack="True" OnSelectedIndexChanged="lstProducts_SelectedIndexChanged" Runat="Server"> <asp:ListItem Text="Hair Dryer"/> <asp:ListItem Text="Shaving Cream"/> <asp:ListItem Text="Electric Comb"/> <asp:ListItem Text="Nail Polish"/> <asp:ListItem Text="French Toast"/> </asp:ListBox> <p> <h2>Shopping Cart:</h2> <asp:ListBox ID="lstCart" Width="200" Runat="Server"/> <br> <asp:Button id="btnRemove" Text="Remove Item" OnClick="btnRemove_Click" Runat="Server"/> <asp:Button id="btnRemoveAll" Text="Remove All" OnClick="btnRemoveAll_Click" Runat="Server"/> </form> </body> </html> The C# version of this code can be found on the CD-ROM. |