Web Form Controls


You have covered the basics of Web applications and Web Forms, how to build a Web application within Visual Studio .NET for a Managed C++ codebehind, and how to set it up for debugging. Now you'll go ahead and make a few Web Forms that actually do something. To do this you need to add, as discussed briefly previously, what ASP.NET calls Web Form controls.

Web Form controls provide you the ability to build a Web interface in a modular fashion. Each Web Form control provides a specific type of input and/or output functionality to your Web Form. For example, there are Web Form controls to place a label or image on the screen, click a button, display and input text data, and select a data item from a list.

All Web Form controls inherit from the WebControl class, which provides a number of standard methods and properties. Each Web Form control has a few methods and properties of its own that make it unique. Also, all Web Form controls have events for which you can create handlers. You can find all controls provided by ASP.NET within the System::Web::UI::WebControls namespace.

Let's take a look at several of the Web Form controls provided by ASP.NET, starting with one of the easiest: Label.

Note

The following descriptions of the common properties used for each control assume that the Web control will be sent to a Cascading Style Sheets, level 1 (CSS1)-compliant browser. If ASP.NET determines that the browser is not CSS1 compliant, it will send HTML that best approximates these properties' functionality.

Note

All properties that update the CSS1 style for a control can be overruled by the ! IMPORTANT CSS1 property.

Label

This useful, yet extremely simple, control allows you to display text at a set location on the page. Unlike static text, which you simply code directly in the .aspx file, you can dynamically change the text that is displayed using the Text property. A neat feature of the Label is that you can embed HTML tags within the text that you add. This makes the Label control extremely flexible.

The properties that you will most likely use with the Label control are as follows:

  • BackColor is a System::Drawing::Color that represents the background color of the control and defaults to Color::Empty. This property gets or sets the CSS1 Style property background-color. You should note that this property will override any previous background-color CSS1 Style properties.

  • Font is a property that gets the FontInfo object associated with the control. You will use the FontInfo object's properties to set the CSS1 Style font-family, font-size, and font-style properties for the control.

  • ForeColor is a System::Drawing::Color that represents the foreground color of the control and defaults to Color::Empty. This property gets or sets the CSS1 Style property foreground-color. Just like BackColor, this property will override any previous foreground-color CSS1 Style properties.

  • Text is a property that gets the text associated with the control. Note that if this property is empty, an empty <span></span> tag is still sent to the browser. The text may contain other HTML tags.

Color.aspx (see Listing 14-7) and Color.aspx.h (see Listing 14-8) are the GUI design and codebehind showing the Label control in action. The Web Form displays an italicized string with a random foreground and background color. To make things more interesting, I added the <meta http-equiv="Refresh" content="1"> tag to cause the form to update with random colors every second. Also, just to show that it can be done, I boldfaced a portion of the displayed string.

Listing 14-7: The ASP.NET GUI Design File Color.aspx

start example
 <%@ Assembly Name="WebForms" %> <%@ Page Inherits="WebForms.ColorfulForm" %> <html>     <head>         <title>Changing Colors</title>         <meta http-equiv="Refresh" content="1">     </head>     <body>         <form  method="post" runat="server">             <asp:Label  runat="server"></asp:Label>         </form>     </body> </html> 
end example

Listing 14-8: The Codebehind Color.aspx.h

start example
 using namespace System; using namespace System::Drawing; using namespace System::Web::UI; using namespace System::Web::UI::WebControls; namespace WebForms {     public __gc class ColorfulForm : public Page     {     protected:         Label *Label;     protected:         void OnLoad(EventArgs *e)         {             Random *r = new Random(); Label->ForeColor =                 Color::FromArgb(r->Next(255),r->Next(255),r->Next(255));             Label->BackColor =                 Color::FromArgb(r->Next(255),r->Next(255),r->Next(255));             Label->Text =                 S"Let's randomly change <b>colors</b> until you get sick "                 S"of watching it";             Label->Font->Italic = true;             Page::OnLoad(e);         }     }; } 
end example

As you can see, the .aspx file is very simple—it's just an empty <asp:Label> control. The real work of the Web Form happens in the codebehind (see Listing 14-8).

In this example, you don't have any event to delegate, so you can safely omit the overriding of OnInit() method. The important overridable method in this example is the OnLoad() method. This method gets executed every time Load event is triggered. Another way of looking at it is that the OnLoad() method will be executed whenever the client browser page is about to be loaded.

Something you should note is that the OnLoad() method is executed before any other Web control events. For example, when you click a button on a control, the OnLoad() method is executed and then the button event. Because this is the case, you need to make sure to code only what you want executed every time the Web Form is loaded within the OnLoad() method.

There is one exception to this. The Page class provides an IsPostBack property that can be checked to see if this is the first time the OnLoad() method has been called for the Web Form for this session. You will look at IsPostBack in more detail later in the chapter.

In the preceding example, you want the same code executed on every Load event, so the OnLoad() method doesn't need to use the IsPostBack property. In this case, the OnLoad() method simply creates a random number generator class and then populates the ForeColor and BackColor properties using the Color class's static FromArgb() method. (You examine this method in detail in Chapter 11.) Next, you set the Italic property within the Font property to true. Finally, you call the base class's version of the OnLoad() method to make sure that any code in the base class's version of the OnLoad() method is also executed.

Figure 14-10 shows a "colorful" black-and-white still image of the Colorful Web Form.

click to expand
Figure 14-10: The Colorful Web Form

Image

Sooner or later you are going to want to add something other than text to your Web Form. The Image control allows you to display images on the page. Unlike the static <img> tag, you can dynamically change the image that is being displayed by changing the ImageUrl property. In addition, it is possible to do things such as resize the image and change its Web Form alignment.

The properties that you will most likely use with the Image control are as follows:

  • AlternateText gets or sets text that will be shown if the image is unavailable for display. For a browser that supports the ToolTip feature, this text is displayed.

  • BorderColor gets or sets a System::Drawing::Color that represents the color of the control's border. It defaults to Color::Empty, which signifies that the property is not set. This property gets or sets the CSS1 Style property border-color.

  • Height gets or sets a Unit object that represents the height of the control. It defaults to Unit::Empty, which signifies that the image should be displayed using its own default height. This property gets or sets the CSS1 Style property height.

  • ImageAlign gets or sets an ImageAlign enum that represents the image's alignment in relationship to other elements on the Web Form. Common image alignments are Left, Right, Baseline, Top, Middle, and Bottom. The default is NotSet, which signifies that the property is not set. This property gets or sets the <img> tag Align attribute.

  • ImageUrl gets or sets the relative or absolute URL of the image to be displayed. This property gets or sets the <img> tag Src attribute.

  • Width gets or sets a Unit object that represents the width of the control. It defaults to Unit::Empty, which signifies that the image should be displayed using its own default width. This property gets or sets the CSS1 Style property width.

Happy.aspx (see Listing 14-9) and Happy.aspx.h (see Listing 14-10) are the GUI design and codebehind showing the Image control in action. The Web Form displays a happy face image expanding or contracting 10 pixels at every Web Form submit.

Listing 14-9: The ASP.NET GUI Design File Happy.aspx

start example
 <%@ Assembly Name="WebForms" %> <%@ Page Inherits="WebForms.Happy" %> <HTML>   <HEAD>     <title>Happy Face</title>   </HEAD>   <body>     <form  method="post" runat="server">       <P>         <asp:image  runat="server"                     ImageUrl="images/Happy.GIF" ImageAlign="Left">         </asp:image>       </P>     </form>   </body> </HTML> <script language="JavaScript">     Happy.submit(); </script> 
end example

Listing 14-10: The Codebehind Color.aspx.h

start example
 using namespace System; using namespace System::Web::UI; using namespace System::Web::UI::WebControls; namespace WebForms {     public __gc class Happy : public Page     {     protected:         WebControls::Image *imgHappy;         void OnLoad(EventArgs *e)         {             if (!IsPostBack)             {                 // Create a session object the first time Web Form is loaded                 Session->Item[S"cSize"] = __box(32);             }             // Copy the session object to local variable for easy access             Int32 cSize = *dynamic_cast<Int32*>(Session->Item[S"cSize"]);             if (cSize % 2 == 1)             {                 cSize -= 10;                 if (cSize < 32)                     cSize = 32;             }             else             {                 cSize += 10;                 if (cSize > 400)                     cSize -= 1;             }             imgHappy->Width = Unit::Pixel(cSize);             imgHappy->Height = Unit::Pixel(cSize);             // Update the session object for next post back             Session->Item[S"cSize"] = __box(cSize);             Page::OnLoad(e);         }     }; } 
end example

This .aspx file demonstrates a simple little trick that you can do using JavaScript. When JavaScript commands are found outside of a function within HTML code, they get executed immediately when encountered by the browser's interpreter. In the preceding example, you applied this trick by adding the following script after all the HTML code:

 <script language="JavaScript">     Happy.submit(); </script> 

What this does is force the Web Form to be immediately submitted after the image is rendered to the client browser. You will see a more usable example of this trick in the "Tables" section later in this chapter when I show you how to update the browser status bar.

Like the previous example, all the code logic of the codebehind falls within the OnLoad() method. The main thing to note about this example is the use of a Session object:

 if (!IsPostBack) {     //  Create a session object the first time Web Form is loaded     Session->Item[S"cSize"] = __box(32); } // Copy the session object to local variable for easy access Int32 cSize = *dynamic_cast<Int32*>(Session->Item[S"cSize"]); //...Use the session object // Update the session object for next post back Session->Item[S"cSize"] = __box(cSize); 

A Session object is extremely handy and allows you to store data between one page load and another within a single session. It is implemented using a Hashtable collection of key/value pairs. The basic syntax to create and update a Session object is this:

 Session->Item[S"String key"] = (Object*) value; 

To get access to the Session object, you use the following syntax:

 Object *value = dynamic_cast<Object*>(Session->Item[S"String key"]); 

The codebehind, once you get past the Session object logic, is fairly straightforward. First, the OnLoad() method uses the IsPostBack variable to see if this is the first page load and if it loads the Session object. Next, it loads a local version of the Session object for faster and easier access to its value. From there, it goes into the main logic of the codebehind, checking to see if the cSize is even or odd. If it is even, the happy face is expanding. If it is odd, the happy face is contracting. Two checks are made to see if you have reached either the minimum or maximum size of the happy face and, if so, the expansion/contraction process is reversed. The width and height of the happy face image are then updated. Finally, the cSize is placed back into the Session object for the next time the OnLoad() method for this particular session is called.

Figure 14-11 shows the happy face image as it starts to contract within the Happy Web Form.

click to expand
Figure 14-11: The Happy Web Form

TextBox

I can almost guarantee that you will need to get some form of textual information from the users of your Web site. The TextBox control is the only Web Form control provided by ASP.NET that lets a user enter text.

Most of the properties that you will use with the TextBox will only be implemented at design time. For example, the TextMode property determines if the text box is SingleLine (the default), MultiLine, or Password. The width of the TextBox is specified by its Columns property. If the TextMode of the TextBox is set to MultiLine, then its height is specified by the Rows property. Under normal conditions, none of these properties would be changed at runtime. (Not that this isn't possible.)

An important property that you will normally leave alone but that occasionally comes in handy is the EnableViewState property. This Boolean property specifies if the state of the text is retained or, in other words, it specifies whether the text within the control remains after a trip from the client to the server and back.

The properties that you will most likely use with the TextBox control are as follows:

  • BackColor is a System::Drawing::Color that represents the background color of the control and defaults to Color::Empty. This property gets or sets the CSS1 Style property background-color.

  • BorderColor is a property that gets or sets a System::Drawing::Color that represents the color of the control's border. It defaults to Color::Empty, which signifies that the property is not set. This property gets or sets the CSS1 Style property border-color.

  • Enabled is a property that gets or sets a Boolean value that specifies if the control is enabled. The default is true.

  • ForeColor is a System::Drawing::Color that represents the foreground color of the control and defaults to Color::Empty. This property gets or sets the CSS1 Style property foreground-color.

  • Text is a property that gets or sets a String value that represents the contents of the control. The default is String::Empty.

ChangeColor.aspx (see Listing 14-11) and ChangeColor.aspx.h (see Listing 14-12) are the GUI design and codebehind showing the TextBox control in action. The Web Form displays a TextBox, which requests the user to enter two colors separated by a comma. The first color is the foreground or text color and the second color is the background color of the TextBox. If you enter an invalid color, then the default color is displayed.

Listing 14-11: The ASP.NET GUI Design File ChangeColor.aspx

start example
 <%@ Assembly Name="WebForms" %> <%@ Page Inherits="WebForms.ChangeColor" %> <HTML>   <HEAD>     <title>Change Color</title>   </HEAD>   <body>     <form  method="post" runat="server">       Enter "foreground color", "background color" then press return:       <asp:TextBox  runat="server" Columns="30"                     AutoPostBack="True">       </asp:TextBox>     </form>   </body> </HTML> 
end example

Listing 14-12: The Codebehind ChangeColor.aspx.h

start example
 using namespace System; using namespace System::Drawing; using namespace System::Web::UI; using namespace System::Web::UI::WebControls; namespace WebForms {     public __gc class ChangeColor : public Page     {     protected:         TextBox *tbChanger;     protected:         void OnInit(EventArgs *e)         {             tbChanger->TextChanged +=                 new EventHandler(this, tbChanger_TextChanged);             Page::OnInit(e);         }     private:         void tbChanger_TextChanged(Object *sender, EventArgs *e)         {             Char AComma[] = {','};             String *incolors[];             // parse out the colors             incolors = tbChanger->Text->Split(AComma);             // change the foreground and background             tbChanger->ForeColor = Color::FromName(incolors[0]);             if (incolors->Length > 1)                 tbChanger->BackColor = Color::FromName(incolors[1]);         }     }; } 
end example

There is not much here of interest, except for the use of the AutoPostBack property within the TextBox. This property causes a post back whenever changes are made to the control. Normally, this post back is triggered when you leave the control by pressing the Tab key or by clicking another control but, because this is the only control on the Web Form, pressing the Enter key also works.

Because the preceding example was only one control, you could have written the codebehind using an OnLoad() method like you did in the previous example. It would even have taken less code. This method makes more sense as you are capturing the change of the text in the TextBox, so why not use the correct event?

By the way, the if statement checking the number of colors entered into the TextBox avoids an exception being thrown. I found this out the hard way.

Figure 14-12 shows in black-and-white the TextBox with a blue background and yellow text. (Guess you will have to take my word on it.)

click to expand
Figure 14-12: The ChangeColor form

Buttons and Hyperlinks

Entering text definitely has its place, but a mouse-click response is a much preferred way of providing input from the user's perspective. It's quick, simple, and the user's hands don't have to leave the mouse. Of course, you can't provide mouse-click responses for everything but, when you do, ASP.NET provides four buttons, a hyperlink, and a button that looks like a hyperlink from which you can choose:

  • Button displays a push button to the user. This Web control is highly configurable to the point where you can change it to look like just a simple label on the Web Form.

  • CheckBox displays a single check box that allows the user to select either a true or false condition. Note that this differs from a Win Form's CheckBox in that there is no Indeterminate state option. Like the TextBox, the CheckBox's state is retained throughout the Web Form's session, unless the EnableViewState property is set to false (something very seldom done).

  • ImageButton displays a push button to the user but, instead of text, the button displays an image.

  • RadioButton displays a single radio button that the user can then select. If the buttons are grouped logically by sharing the same GroupName, then the user can select one radio button within the group and have all the others clear automatically.

  • HyperLink displays a control that provides a link to another location in the current page or to a different Web page. Normally, you display the HyperLink as text by specifying the Text property. You can also display it as an image by specifying the ImageUrl property. If you specify both the Text and ImageUrl properties, then ImageUrl takes precedence.

  • LinkButton displays a control that has the look and feel of a hyperlink but acts like a standard button. Personally, I would use this button to submit the current form and then transfer control to another Web Form, but there are no rules anywhere that say you can't use this button as an ordinary button (or an overkill hyperlink, for that matter, as shown in the following example).

Other than the Enable and Visible properties, in most cases, you will not be dealing with the properties of a button in the codebehind. Instead, you will configure the button in the design code and then simply handle the Click event of the button.

As you can probably guess, the Enable property specifies whether the button is or is not accessible to the user but is still displayed on the client browser. The Visible property makes the button disappear. In fact, if a button is invisible, the button does not even get sent to the client browser.

The CheckBox and RadioButton are a little different from the other buttons in that you will also need to work with the Checked property. The Checked property specifies whether the control has been selected or not.

Buttons.aspx (see Listing 14-13) and Buttons.aspx.h (see Listing 14-14) are the GUI design and codebehind showing buttons and hyperlinks in action. The Web Form looks a lot more complex than it is. It is just a four-cell table grouped by the button type. Each cell provides three buttons to select the three Web Forms created previously in the chapter.

Listing 14-13: The ASP.NET GUI Design File Buttons.aspx

start example
 <%@ Assembly Name="WebForms" %> <%@ Page Inherits="WebForms.Buttons" %> <HTML>   <HEAD>     <title>Buttons</title>   </HEAD>   <body>     <form  method="post" runat="server">       <TABLE cellSpacing="4" cellPadding="4" border="2">         <TR>           <TD>             <asp:radiobutton  runat="server" AutoPostBack="True"                                Text="Colorful" GroupName="PageGroup">             </asp:radiobutton>             <P>             <asp:radiobutton  runat="server" AutoPostBack="True"                                Text="Happy Face" GroupName="PageGroup">             </asp:radiobutton>             <P>             <asp:radiobutton  runat="server" AutoPostBack="True"                                Text="TextBox Color" GroupName="PageGroup">             </asp:radiobutton>           </TD>           <TD>             <asp:checkbox  runat="server" Text="Colorful">             </asp:checkbox>             <P>             <asp:checkbox  runat="server" Text="Happy Face">             </asp:checkbox>             <P>             <asp:checkbox  runat="server" Text="TextBox Color">             </asp:checkbox>             <P>             <asp:button  runat="server" Text="Go to first checked box">             </asp:button>           </TD>         </TR>         <TR>           <TD>             <asp:button  runat="server" Text="Colorful"                          ForeColor="Navy" BorderColor="Purple"                          BackColor="PaleGreen">             </asp:button>             <P>             <asp:imagebutton  runat="server" BorderStyle="Outset"                               ImageUrl="images/Happy.GIF">             </asp:imagebutton>             <P>             <asp:button  runat="server" Text="TextBox Color">             </asp:button>           </TD>           <TD>             <asp:hyperlink  runat="server"                             NavigateUrl="Color.aspx">               Colorful             </asp:hyperlink>             <P>             <asp:HyperLink  runat="server" NavigateUrl="Happy.aspx"                             ImageUrl="images/Happy.GIF">               Happy Face             </asp:HyperLink>             <P>             <asp:LinkButton   runat="server">               TextBox Color             </asp:LinkButton>           </TD>         </TR>       </TABLE>     </form>   </body> </HTML> 
end example

Listing 14-14: The Codebehind Buttons.aspx.h

start example
 using namespace System; using namespace System::Drawing; using namespace System::Web::UI; using namespace System::Web::UI::WebControls; namespace WebForms {     public __gc class Buttons : public Page     {     protected:         // Row 1 Column 1 - Controls         RadioButton *rbColorful;         RadioButton *rbHappy;         RadioButton *rbChange;         // Row 1 Column 2 - Controls         CheckBox    *cbColorful;         CheckBox    *cbHappy;         CheckBox    *cbChange;         Button      *bnCheckBoxes;         // Row 2 Column 1 - Controls         Button      *bnColorful;         ImageButton *ibnHappy;         Button      *bnChange;         // Row 2 Column 2 - Control         LinkButton  *lbnChange;         void OnInit(EventArgs *e)         {             // Row 1 Column 1 - Event Delegations             rbColorful->CheckedChanged += new EventHandler(this, RB_ChkChanged);             rbHappy->CheckedChanged    += new EventHandler(this, RB_ChkChanged);             rbChange->CheckedChanged   += new EventHandler(this, RB_ChkChanged);             // Row 1 Column 2 - Event Delegation             bnCheckBoxes->Click += new EventHandler(this, bnCheckBoxes_Click);             // Row 2 Column 1 - Event Delegations             bnColorful->Click += new EventHandler(this, bnColorful_Click);             ibnHappy->Click += new ImageClickEventHandler(this, ibnHappy_Click);             bnChange->Click   += new EventHandler(this, bnChange_Click);             // Row 2 Column 2 - Event Delegation             lbnChange->Click += new EventHandler(this, lbnChange_Click);             Page::OnInit(e);         }     private:         // Row 1 Column 1 - Event Handler         void RB_ChkChanged(Object *sender, EventArgs *e)         {             if (rbColorful->Checked)                 Response->Redirect(S"Color.aspx");             else if (rbHappy->Checked)                 Response->Redirect(S"Happy.aspx");             else if (rbChange->Checked)                 Response->Redirect(S"ChangeColor.aspx");         }         // Row 1 Column 2 - Event Handler         void bnCheckBoxes_Click(Object *sender, EventArgs *e)         {             if (cbColorful->Checked)                 Response->Redirect(S"Color.aspx");             else if (cbHappy->Checked)                 Response->Redirect(S"Happy.aspx");             else if (cbChange->Checked)                 Response->Redirect(S"ChangeColor.aspx");         }         // Row 2 Column 1 - Event Handlers         void bnColorful_Click(Object *sender, EventArgs *e)         {             Response->Redirect(S"Color.aspx");         }         void ibnHappy_Click(Object *sender, ImageClickEventArgs *e)         {             Response->Redirect(S"Happy.aspx");         }         void bnChange_Click(Object *sender, EventArgs *e)         {             Response->Redirect(S"ChangeColor.aspx");         }         // Row 2 Column 2 - Event Handler         void lbnChange_Click(Object *sender, EventArgs *e)         {             Response->Redirect(S"ChangeColor.aspx");         }     }; } 
end example

There is no special coding in the preceding design code. You might want to notice the use of standard HTML table tags. Later in this chapter, you will see Table control, which is a lot different coding-wise but very similar functionality-wise.

The Buttons codebehind has a few things worth noting. The first is that you can have multiple events handled by the same event handler. In the preceding example, you see this done with the RadioButton control's CheckedChanged events (which, incidentally, you also set for AutoPostBack in each RadioButton):

 rbColorful->CheckedChanged += new EventHandler(this,RadioButton_CheckedChanged); rbHappy->CheckedChanged += new EventHandler(this, RadioButton_CheckedChanged); rbChange->CheckedChanged += new EventHandler(this, RadioButton_CheckedChanged); 

You might also note that only the handler for the control that actually gets clicked is triggered even though the name of the event seems to imply that both the radio button that was checked and the radio button that became unchecked should also be triggered (as it changed also). Because of this, it would also have been possible to code this example by checking which control sent the event and then processing for that event. This makes the checked property unneeded:

 void RadioButton_CheckedChanged(Object *sender, EventArgs *e) {     if (sender == rbColorful)         Response->Redirect(S"Colorful.aspx");     else if (sender == rbHappy)         Response->Redirect(S"Happy.aspx");     else if (sender == rbChange)         Response->Redirect(S"ChangeColor.aspx"); } 

Another thing that might cause you a few minutes of research (although after reading this, this should not be the case) is that ImageButtons differ from all the other button Click events, in that they use a different event handler. They use ImageClickEventHandler instead of the more standard EventHandler:

 ibnHappy->Click += new ImageClickEventHandler(this, ibnHappy_Click); 

Probably the most important thing shown in the preceding example is how to programmatically jump to a new Web page using the Redirect() method within the Response property of the Page class:

 Response->Redirect(S"Colorful.aspx"); 

The preceding example shows how to jump to a local Web Form. To jump to a Web Form on a different server, you need to use the full URL, starting with http://:

 Response->Redirect(S"http://www.contentmgr.com/default.aspx"); 

Figure 14-13 shows an assortment of buttons from which you can select the previous examples.

click to expand
Figure 14-13: The Buttons form

Lists

A list control is really nothing more than a control that displays a list of items in the client browser. Many of the list controls provided by ASP.NET allow for user input, but that is not a requirement for it to be a list control. ASP.NET provides seven list controls to choose from:

  • DataGrid displays the fields of a data source as columns in a table. Each row represents a record in the data source. The DataGrid not only supports the display of a list of items, but it also allows for selecting, editing, deleting, paging, and sorting.

  • DataList displays a data bound list using a template. The DataList supports displaying, selecting, and editing of its items.

  • DropDownList displays a single, select drop-down list control of ListItem objects. You can create the DropDownList using a data bound list as well.

  • CheckBoxList displays a multiselect check box grouped list of ListItem objects. You can dynamically create the CheckBoxList using a data bound list. This control provides the same functionality as that of the standard CheckBox control, with the added benefit of data binding, but at the expense of fewer formatting choices.

  • ListBox displays a single or multiselect list box control of ListItem objects. You can create the ListBox using a data bound list as well.

  • RadioButtonList displays a single, select radio button grouped list of ListItem objects. You can dynamically create the RadioButtonList using a data bound list. This control provides the same functionality as that of the standard RadioButton control, with the added benefit of data binding, but at the expense of fewer formatting choices.

  • Repeater displays a data bound list. The Repeater does not support format templating, selecting, or editing of its items.

In the preceding list, it was shown that list controls display bound data. Basically, bound data are collections that support the IEnumerable, ICollection, or IListSource interface. In other words, you can display the collections discussed in Chapter 7 and the DataView, DataSet, and DataReader objects discussed in Chapter 12 using list controls.

Two members that all list controls have in common are the DataSource property and the DataBind() method. To dynamically create a list requires you to use both members together. The DataSource property associates a bound data source with the list control. The DataBind() method then binds the data source to the control. A common mistake is to forget to call DataBind(). You will know when you have done this because you will get no data being displayed in the list control for which you have set the DataSource property.

To determine which item was selected, you will probably use the SelectedItem property. You can use the SelectedIndex property in conjunction with the Items property but, as you can see here, using SelectedItem is much easier:

 String *val1 = listBox->SelectedItem->Value; String *val2 = listBox->Items->Item[listBox->SelectedIndex]->Value; 

To set an item in a list control as selected, you use the SelectedIndex property:

 listBox->SelectedIndex = 3;   // remember items start at an index of 0 

Remember, the Repeater control doesn't allow for item selection, therefore it doesn't define either the SelectedItem property or the SelectedIndex property.

Lists.aspx (see Listing 14-15) and Lists.aspx.h (see Listing 14-16) are the GUI design and codebehind showing a few list controls in action. You might want to pay attention to this example as it shows how to extract the tables out of an OLE DB database and place them in a table for selection. Once the table is selected, a DataGrid of the table displays all the content of the table. Personally, I think this example may come in handy in your future. I also threw in a drop-down control that changes the background color of the DataGrid control to show how to manually create a list control.

Listing 14-15: The ASP.NET GUI Design File Lists.aspx

start example
 <%@ Assembly Name="WebForms" %> <%@ Page Inherits="WebForms.Lists" %> <HTML>   <HEAD>     <title>Lists</title>   </HEAD>   <body>     <form  method="post" runat="server">       <P>         <asp:ListBox  runat="server" AutoPostBack="True">         </asp:ListBox>       </P>       <P>         <asp:DataGrid  runat="server">         </asp:DataGrid>       </P>       <P>         <asp:DropDownList  runat="server"                             Enabled="False" AutoPostBack="True">           <asp:ListItem Value="white">Select Background Color</asp:ListItem>         </asp:DropDownList>       </P>     </form>   </body> </HTML> 
end example

Listing 14-16: The Codebehind Lists.aspx.h

start example
 using namespace System; using namespace System::Data; using namespace System::Data::OleDb; using namespace System::Drawing; using namespace System::Web::UI; using namespace System::Web::UI::WebControls; namespace WebForms {     public __gc class Lists : public Page     {     protected:         ListBox      *selListBox;         DataGrid     *dataGrid;         DropDownList *colorList;         void OnLoad(EventArgs *e)         {             OleDbConnection *con;             try             { #ifdef OLEDBAuth                  //  SOL Server authentication                  String *conStr = S"Provider=SQLOLEDB.1;"                      S"User ID=sa; Password=;"                      S"Data Source=(local); Initial Catalog=DCV_DB;"; #else                  // Windows Integrated Security                  String *conStr = S"Provider=SQLOLEDB.1;"                     S"Persist Security Info=False; Integrated Security=SSPI;"                     S"Data Source=(local); Initial Catalog=DCV_DB;"; #endif                 con = new OleDbConnection(conStr);                 con->Open();                 if (!IsPostBack)                 {                     // Set up database table list box                     Object *restrict[] = {0, 0, 0, S"TABLE"};                     DataTable *dt =                         con->GetOleDbSchemaTable(OleDbSchemaGuid::Tables,                                                    restrict);                     selListBox->DataSource = dt->DefaultView;                     selListBox->DataTextField = S"TABLE_NAME";                     selListBox->DataBind();                     // Set up Background color list box                     colorList->Items->Add(S"Yellow");                     colorList->Items->Add(new ListItem(S"Green",S"LightGreen"));                     colorList->Items->Add(S"Red");                 }                 else                 {                     // Build data grid from selected database table                     String *selectedTable = selListBox->SelectedItem->Value;                     String *Cmd =                         String::Concat(S"SELECT * FROM ", selectedTable);                     OleDbDataAdapter *dAdapt = new OleDbDataAdapter(Cmd, con);                     DataSet *dSet = new DataSet();                     dAdapt->Fill(dSet);                     dataGrid->DataSource = dSet;                     dataGrid->DataBind();                     dataGrid->BackColor =                         Color::FromName(colorList->SelectedItem->Value);                     // enable background color list box                     colorList->Enabled = true;                 }             }             catch(Exception *exp)             {                 // Do Exception handling                 throw exp;             }             __finally             {                 // Close down the database                 con->Close();             }         }     }; } 
end example

There's nothing new in this design file other than it disables the drop-down list when the Web Form is first created. It doesn't make sense to have it enabled until there's a DataGrid for which to change the background.

This codebehind could have been written so that processing was handled within SelectedIndexChange event handlers, but as I started coding, I realized that the same code was being executed no matter which control event was triggered. The only time this differed was on the initial Web Form generated. In other words, the same code was always run on every post back—only the initial post did something different. Because this was the case, it was possible to write all the logic within the OnLoad() method, as seen previously, because the OnLoad() method is called for every post back.

The first thing the OnLoad() method does is open up the database. Then if this is the first time the Web Form is loaded, it creates two list controls. The first is a ListBox of all the tables within the database. The second is a DropDownList of all the colors that the DataGrid background can be set to.

To get all the tables in a database, you need to use the GetOleDbSchemaTable() method. The first parameter you pass is an OleDbSchemaGuid value that specifies the schema table to return. The second parameter is an array of restriction values. To get the tables in the database, you need to first pass OleDbSchemaGuid::Tables, which specifies that you want the schema table of all the tables in the database. Then you restrict the fourth column to "TABLE". The valid restrictions for the fourth column are "ALIAS", "TABLE", "SYNONYM", "SYSTEM TABLE", "VIEW", "GLOBAL TEMPORARY", "LOCAL TEMPORARY", and "SYSTEM VIEW".

 Object *restrict[] = {0, 0, 0, S"TABLE"}; DataTable *dt = con->GetOleDbSchemaTable(OleDbSchemaGuid::Tables, restrict); 

When the GetOleDbSchemaTable() method returns, you have a DataTable containing information about the tables in the database. Now all you have to do is place the column in the DataTable containing the table name in the ListBox. You do this by first making the default view of the DataTable the data source of the ListBox and then selecting the TABLE_NAME column to be used as the item to be displayed in the ListBox using the DataTextField property. Don't forget to call the DataBind() method:

 selListBox->DataSource = dt->DefaultView; selListBox->DataTextField = S"TABLE_NAME"; selListBox->DataBind(); 

To build a list control dynamically, you use the Add() method found within the Items property. Then you can either add a ListItem object, which allows you to specify different Text and Value properties to the list control, or add a String object, which sets the Text and Value to the same value (the passed String).

 colorList->Items->Add(new ListItem(S"Green",S"LightGreen")); colorList->Items->Add(S"Red"); 

By the way, it is also possible to Insert(), Remove(), and Clear() ListItems from a list control.

On a post back, the OnLoad() method does not need to load the Tables or Colors list control because the Web Form will retain the list control information and state between post backs. Instead, what needs to be built is the DataGrid of the contents of the selected Table. You do this by assigning the DataSet of the Table's contents to the DataGrid and then calling DataBind(). You saw how to create a DataSet in Chapter 12.

 String *selectedTable = selListBox->SelectedItem->Value; String *Cmd = String::Concat(S"SELECT * FROM ", selectedTable); OleDbDataAdapter *dAdapt = new OleDbDataAdapter(Cmd, con); DataSet *dSet = new DataSet(); dAdapt->Fill(dSet); dataGrid->DataSource = dSet; dataGrid->DataBind(); 

You grab the background color to display out of the color drop-down list. Notice that the first time this is called, the drop-down list is not enabled and its value is White, even though the text says "Select Background Color". Once you have created a DataGrid, you can then enable the color drop-down list.

 dataGrid->BackColor = Color::FromName(colorList->SelectedItem->Value); // enable background color list box colorList->Enabled = true; 

Figure 14-14 shows the content of the Content database table, with a green background. (I know it looks gray to you, but it really is green—honest.)

click to expand
Figure 14-14: The list form

Tables

You are probably very familiar with the HTML table tag. You might be wondering why you would need another table in the form of a control. The answer is primarily its ability to be dynamically maintained within ASP.NET. With the Table control, you have much more flexibility and control when it comes to dynamically changing the look and feel of the content, layout, and so forth of your tables. Ultimately, though, the HTML generated will be standard HTML table tags.

When you work with the Table control, you will be working primarily with three classes:

  • Table defines the properties and creates a table.

  • TableRow represents a row of a Table control.

  • TableCell represents a single cell or column in a row of a Table control.

Unlike some of the other controls described previously, the Table control is designed to be used programmatically. Thus, you will be frequently working with the members of the Table control in the codebehind, instead of setting them once within the GUI design file.

Some of the more common properties of the Table control are as follows:

  • BackColor is a System::Drawing::Color that represents the background color of the control and defaults to Color::Empty. This property gets or sets the CSS1 Style property background-color.

  • BackImageUrl is the URL of the background image to display behind the table. The image will be tiled if it is smaller than the table.

  • BorderColor is a System::Drawing::Color that represents the color of the control's border. It defaults to Color::Empty, which signifies that the property is not set. This property gets or sets the CSS1 Style property border-color.

  • BorderWidth is a Unit object that represents the width of the border of the control. It defaults to Unit::Empty, which signifies that the default width of 1 pixel is used. Note that if the GridLines property is not set, then this property is ignored.

  • CellPadding is the distance in pixels (only) between the border and the contents of the table's cell.

  • CellSpacing is the distance in pixels (only) between each table cell.

  • ForeColor is a System::Drawing::Color that represents the foreground color of the control and defaults to Color::Empty. This property gets or sets the CSS1 Style property foreground-color.

  • GridLines is a GridLine enum that represents whether the table displays grid lines and, if so, whether the lines are vertical, horizontal, or both. The default is no grid lines.

  • HorizontalAlign is a HorizontalAlign enum that represents the horizontal alignment of the table within the Web Form.

  • Rows is a TableRowCollection that represents the rows within the table. You use this control to add rows to the Table control.

Like the Table control, you will be working frequently with TableRow control's properties. Many of the properties of the TableRow are the same as those of the Table control. Where they are the same, the TableRow control property overrules the Table control's property. Here are some of the more common TableRow controls:

  • BackColor is a System::Drawing::Color that represents the background color of the control and defaults to Color::Empty. This property gets or sets the CSS1 Style property background-color.

  • Cells is a TableCellCollection that represents the cell within the row. You use this control to add TableCells to the TableRow control.

  • ForeColor is a System::Drawing::Color that represents the foreground color of the control and defaults to Color::Empty. This property gets or sets the CSS1 Style property foreground-color.

  • Height is a property that gets or sets a Unit object that represents the height of the control. It defaults to Unit::Empty, which signifies that the row should be determined based on the height of the tallest cell.

  • Width is a property that gets or sets a Unit object that represents the width of the control. It defaults to Unit::Empty, which signifies that the row should be determined based on the smaller of the sum of the widths of the cells and the width of the browser client window.

Just like the other two table controls, you will be frequently using TableCell control properties—if you are creating tables, that is. There are also many common properties among all three table controls. The TableCell control property ultimately overrules all others. Here are some of the more common TableCell properties:

  • BackColor is a System::Drawing::Color that represents the background color of the control and defaults to Color::Empty. This property gets or sets the CSS1 Style property background-color.

  • ColumnSpan is an integer value that represents the number of columns the TableCell spans.

  • Controls is a ControlCollection that represents the controls within the cell. You use this control to add controls to the TableCell control.

  • ForeColor is a System::Drawing::Color that represents the foreground color of the control and defaults to Color::Empty. This property gets or sets the CSS1 Style property foreground-color.

  • Height is a property that gets or sets a Unit object that represents the height of the control. It defaults to Unit::Empty, which signifies that the cell should be determined based on the height of its tallest control.

  • HorizontalAlign is a HorizontalAlign enum that represents the horizontal alignment of the cell.

  • RowSpan is an integer value that represents the number of rows the TableCell spans.

  • Text is a String that represents the text contents of the TableCell. The property defaults to the value of String::Empty.

  • ToolTip is a String that represents the text that is displayed when the mouse hovers over the TableCell. The property defaults to the value of String::Empty.

  • VerticalAlign is a VerticalAlign enum that represents the vertical alignment of the cell.

  • Width is a property that gets or sets a Unit object that represents the width of the control. It defaults to Unit::Empty, which signifies that the row should be determined based on the smaller of the sum of the widths of the cells and the width of the browser client window.

  • Wrap is a Boolean value that specifies if the content of the TableCell wraps when the width of the cell is insufficient. The property defaults to true.

When you create tables using the Table control, you will be in essence coding the same steps every time. The basic steps to building a table using the Table control are as follows:

  1. Create a Table control via the GUI design file.

  2. Create a TableRow.

  3. Create a TableCell.

  4. Create a Web Form control.

  5. Place the control in the TableCell.

  6. Place the TableCell in the TableRow.

  7. Repeat steps 3 through 6 for each TableCell in the TableRow.

  8. Place the TableRow in the Table.

  9. Repeat steps 2 through 8 for each TableRow in the Table.

Caution

Programmatic changes made to a Table control are not persistent across post backs. Therefore, any changes you make to TableRows and/or TableCells need to be reconstructed after each post back. If you expect substantial changes, then you should use the Data List or DataGrid controls instead.

Tables.aspx (see Listing 14-17) and Tables.aspx.h (see Listing 14-18) are the GUI design and codebehind showing a table control in action. This Web Form displays all the files in the Web Form root directory along with a little information about each. Also, hidden in the code is how to update the status bar of the browser client.

Listing 14-17: The ASP.NET GUI Design File Tables.aspx

start example
 <%@ Assembly Name="WebForms" %> <%@ Page Inherits="WebForms.Tables" %> <HTML> <HEAD>   <title>Tables</title> </HEAD> <body>   <form  method="post" runat="server">     <asp:Table  runat="server" GridLines="Both">       <asp:TableRow>         <asp:TableCell Text="Name"></asp:TableCell>         <asp:TableCell Text="Created"></asp:TableCell>         <asp:TableCell Text="Length"></asp:TableCell>         <asp:TableCell Text="Attributes"></asp:TableCell>         <asp:TableCell Style="FONT-SIZE: XX-small" Text="Make Happy">         </asp:TableCell>       </asp:TableRow>     </asp:Table>   </form> </body> </HTML> 
end example

Listing 14-18: The Codebehind Tables.aspx.h

start example
 using namespace System; using namespace System::IO; using namespace System::Web::UI; using namespace System::Web::UI::WebControls; namespace WebForms {     public __gc class Tables : public System::Web::UI::Page     {     protected:         // Create a Table control (Step 1)         Table *FilesTable;         void OnLoad(EventArgs *e)         {             LiteralControl *lit;             TableCell      *cell;             String *files[] = Directory::GetFiles(Server->MapPath("."));             for (Int32 i = 0; i < files->Length; i++)             {                 FileInfo *finfo = new FileInfo(files[i]);                 if (!finfo->Exists)                     continue;                 // Create a TableRow (Step 2)                 TableRow *row = new TableRow();                 // Create a TableCell (Step 3)                 cell = new TableCell();                 // Create a Web Form control (Step 4)                 // Creating a hyperlink control                 HyperLink *link = new HyperLink();                 link->Text = finfo->Name;                 link->NavigateUrl = finfo->FullName;                 // Place the control in the TableCell (Step 5)                 cell->Controls->Add(link);                 // Place the TableCell in the TableRow (Step 6)                 row->Cells->Add(cell);                 // Repeat steps 3 through 6 (Step 7)                 // Creating a literal control                 lit = new LiteralControl(                     String::Concat(finfo->CreationTime.ToShortDateString(),                                     S" ",                                     finfo->CreationTime.ToLongTimeString()));                 cell = new TableCell();                 cell->Controls->Add(lit);                 row->Cells->Add(cell);                 lit = new LiteralControl(finfo->Length.ToString());                 cell = new TableCell();                 cell->Controls->Add(lit);                 row->Cells->Add(cell);                 lit = new LiteralControl(__box(finfo->Attributes)->ToString());                 cell = new TableCell();                 cell->Controls->Add(lit);                 row->Cells->Add(cell);                 // Creating an image button control                 ImageButton *ibn = new ImageButton();                 ibn->Command += new CommandEventHandler(this, btnHappy);                 ibn->ImageUrl = S"Images/Happy.gif";                 ibn->CommandArgument = finfo->Name;                 cell = new TableCell();                 cell->HorizontalAlign = HorizontalAlign::Center;                 cell->Controls->Add(ibn);                 row->Cells->Add(cell);                 // Place Row in Table (Step 8)                 FilesTable->Rows->Add(row);             // Repeat steps 2 through 8 (Step 9)             }         }     private:         void btnHappy(Object *sender, CommandEventArgs *e)         {             this->Controls->Add(new LiteralControl(String::Concat(                 S"<script language=javascript>"                 S"window.status='The file ", e->CommandArgument,                 S" is now happy'"                 S"</script>"                 )));         }     }; } 
end example

It would have been perfectly legitimate to have created the entire table in the codebehind, but because I know that the headings will always be the same, I thought it better to place them within the GUI design file. Notice that you can use CSS1 Style within the Table classes. I show only styles being done in the TableCell, but you can do it within the other controls as well.

The preceding example shows how you can place a hyperlink, three literals, and an image button within TableCells of a Table control.

Two things worth noting are the use of the CommandEventHandler and the updating of the browser status bar. The CommandEventHandler allows you to delegate an event and pass it an argument of your choosing. This process is done in two steps. First, you delegate an event handler to the Command event. Second, you place the argument you want to pass on the CommandArgument property. In the preceding example, I pass the name of the file that I want to make happy on the CommandArgument property. Now, when the event is triggered as you click the image button, the handler is called along with the parameter passed. I use this parameter to specify which file is happy on the browser's status bar.

If you recall, earlier in the chapter I pointed out that JavaScript, when placed out of a function call, gets called immediately when encountered. I use that to my advantage in the preceding example. What is happening here is that I am placing a string literal in the HTML stream that gets sent to the client browser. This literal happens to also be JavaScript code. So, when the browser interpreter is parsing the HTML, it encounters the JavaScript, runs it, and then continues on. In this case, the JavaScript calls the window.status method, which updates the status bar with the string assigned to it. Pretty neat, don't you think?

Figure 14-15 shows all the files in the Web Form's root directory as well as a happy file. Look at the status bar.

click to expand
Figure 14-15: The Tables form




Managed C++ and. NET Development
Managed C++ and .NET Development: Visual Studio .NET 2003 Edition
ISBN: 1590590333
EAN: 2147483647
Year: 2005
Pages: 169

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net