![]() ![]() |
5.8 TablesTables are very important in web page design, as they are one of the primary means of controlling the layout on the page. In pure HTML, there are several tags for creating and formatting tables, and many of those have analogs in ASP controls. If you don't need server-side capabilities, then you are just as well off using the static HTML tags. But when you need to control the table at runtime, then ASP controls are the way to go. (You could also use HTML Server controls, described earlier in this chapter, but they don't offer the consistency of implementation and object model that ASP controls offer.) Table 5-10 summarizes the ASP controls used to create tables in web pages.
There is some overlap in the functionality of Table controls and the DataList controls, such as the Repeater, DataList, and DataGrid, covered in detail in Chapter 9. All can be used to display data in a table or list formatted layout. In fact, all of these controls render to the browser (or have the option to render) as HTML tables. (You can verify this by going to your browser and viewing the source of the page displayed.) Table 5-11 summarizes the differences between these four controls.
Example 5-29 demonstrates most of the basic table functionality using C#. Example 5-30 does the same in VB.NET. In these examples, you will use a CheckBoxList control and a RadioButtonList control to set attributes of the font samples displayed in the table. Then a table that contains a sample of every font installed on your system is created. The finished product is shown in Figure 5-16. Example 5-29. Table control using C#, csASPTable.aspx<%@ Page Language="C#" %> <%@import namespace="System.Drawing" %> <%@import namespace="System.Drawing.Text" %> <script runat="server"> void Page_Load(Object Source, EventArgs E) { string str = "The quick brown fox jumped over the lazy dogs."; int i = 0; // Get the style checkboxes. bool boolUnder = false; bool boolOver = false; bool boolStrike = false; foreach(ListItem li in cblFontStyle.Items) { if (li.Selected == true) { switch (li.Value) { case "u": boolUnder = true; break; case "o": boolOver = true; break; case "s": boolStrike = true; break; } } } // Get the font size. int size = Convert.ToInt32(rblSize.SelectedItem.Value); // Get a list of all the fonts installed on the system // Populate the table with the fonts and sample text. InstalledFontCollection ifc = new InstalledFontCollection( ); foreach( FontFamily ff in ifc.Families ) { TableRow r = new TableRow( ); TableCell cFont = new TableCell( ); cFont.Controls.Add(new LiteralControl(ff.Name)); r.Cells.Add(cFont); TableCell cText = new TableCell( ); Label lbl = new Label( ); lbl.Text = str; // ID not necessary here. This just to show it can be set. i++; lbl.ID = "lbl" + i.ToString( ); // Set the font name lbl.Font.Name = ff.Name; // Set the font style if (boolUnder) lbl.Font.Underline = true; if (boolOver) lbl.Font.Overline = true; if (boolStrike) lbl.Font.Strikeout = true; // Set the font size. lbl.Font.Size = size; cText.Controls.Add(lbl); r.Cells.Add(cText); tbl.Rows.Add(r); } } void cblFontStyle_Init(Object Source, EventArgs E) { // create arrays of items to add string[] FontStyle = {"Underline","OverLine", "Strikeout"}; string[] Code = {"u","o","s"}; int i; for (i = 0; i < FontStyle.GetLength(0); i++) { // Add both Text and Value this.cblFontStyle.Items.Add(new ListItem(FontStyle[i],Code[i])); } } </script> <html> <body> <form runat="server"> <h1>ASP Controls</h1> <h2>Table Control</h2> <table> <tr> <td> <strong>Select a Font Style:</strong> </td> <td> <asp:CheckBoxList id="cblFontStyle" autoPostBack="true" cellPadding="5" cellSpacing="10" repeatColumns="3" textAlign="right" onInit="cblFontStyle_Init" runat="server"> </asp:CheckBoxList> </td> </tr> <tr> <td> <strong>Select a Font Size:</strong> </td> <td> <asp:radioButtonList id="rblSize" autoPostBack="true" cellSpacing="20" repeatColumns="3" textAlign="right" repeatDirection="Horizontal" runat="server"> <asp:ListItem text="10pt" value="10"/> <asp:ListItem text="12pt" value="12" selected = "true"/> <asp:ListItem text="14pt" value="14"/> <asp:ListItem text="16pt" value="16"/> <asp:ListItem text="18pt" value="18"/> <asp:ListItem text="24pt" value="24"/> </asp:radioButtonList> </td> </tr> </table> <asp:table id="tbl" backImageUrl="Sunflower Bkgrd.jpg" font-Name="Times New Roman" Font-Size="12" GridLines="Both" CellPadding="10" CellSpacing="5" HorizontalAlign="Left" Width="100%" runat="server"> <asp:TableRow horizontalAlign="Left"> <asp:TableHeaderCell> Font Family </asp:TableHeaderCell> <asp:TableHeaderCell Width="80%"> Sample text </asp:TableHeaderCell> </asp:TableRow> </asp:table> </form> </body> </html> Figure 5-16. Table control![]() In Example 5-30, you can see the event handler methods in VB.NET. I have not included the HTML, since it is identical with that in Example 5-29. Example 5-30. Event handlers for Table control using VB.NET, vbASPTable.aspx<%@ Page Language="VB" %> <%@import namespace="System.Drawing" %> <%@import namespace="System.Drawing.Text" %> <script runat="server"> sub Page_Load(ByVal Sender as Object, _ ByVal e as EventArgs) dim str as string = "The quick brown fox jumped over the lazy dogs." dim i as integer = 0 ' Get the style checkboxes. dim boolUnder as Boolean = false dim boolOver as Boolean = false dim boolStrike as Boolean = false dim li as ListItem for each li in cblFontStyle.Items if li.Selected then select case li.Value case "u" boolUnder = true case "o": boolOver = true case "s": boolStrike = true end select end if next li ' Get the font size. dim size as integer = Convert.ToInt32(rblSize.SelectedItem.Value) ' Get a list of all the fonts installed on the system ' Populate the table with the fonts and sample text. dim ifc as InstalledFontCollection = new InstalledFontCollection( ) dim ff as FontFamily for each ff in ifc.Families dim r as TableRow = new TableRow( ) dim cFont as TableCell = new TableCell( ) cFont.Controls.Add(new LiteralControl(ff.Name)) r.Cells.Add(cFont) dim cText as TableCell = new TableCell( ) dim lbl as Label = new Label( ) lbl.Text = str ' ID not necessary here. This just to show how it can be set. i = i + 1 lbl.ID = "lbl" & i.ToString( ) ' Set the font name lbl.Font.Name = ff.Name ' Set the font style if boolUnder then lbl.Font.Underline = true end if if boolOver then lbl.Font.Overline = true end if if boolStrike then lbl.Font.Strikeout = true end if ' Set the font size. lbl.Font.Size = new FontUnit(size) cText.Controls.Add(lbl) r.Cells.Add(cText) tbl.Rows.Add(r) next ff end sub sub cblFontStyle_Init(ByVal Sender as Object, _ ByVal e as EventArgs) ' create arrays of items to add dim FontStyle( ) as string = {"Underline","OverLine", "Strikeout"} dim Code( ) as string= {"u","o","s"} dim i as integer for i = 0 to FontStyle.GetLength(0) -1 ' Add both Text and Value cblFontStyle.Items.Add(new ListItem(FontStyle(i),Code(i))) next end sub </script> Example 5-29 and Example 5-30 begin with a few directives: <%@ Page Language="C#" %> <%@import namespace="System.Drawing" %> <%@import namespace="System.Drawing.Text" %> The first is a Page directive, one we have seen before—it tells the compiler that the language used is C# (or VB in the case of Example 5-30). The next two are Import directives, which import namespaces. These import directives perform the same function as the using statement in C# or the Imports statement in VB.NET. Directives are described in detail in Chapter 6. Before delving into the script block in detail, hop down to the <body> of the page. After some opening headers, there is a standard, plain vanilla HTML table. This uses the familiar <table> tags enclosing table rows (<tr>), which enclose table cells (<td>). There is nothing dynamic going on here, just the common technique of using a table to control the layout of the page. The second cell of the first row contains an ASP CheckBoxList control, and the second cell of the second row contains an ASP RadioButtonList control, both of which have been discussed earlier in this chapter. Both of these controls have several things in common: an id attribute, the all-important runat attribute, and AutoPostBack set to true, so that any changes will take effect immediately. Both controls also have various other attributes to give the layout I wanted. Notice that the CheckBoxList control has an event handler defined for initialization, onInit , which points to a method called cblFontStyle_Init. This method is in the script block at the top of the page. Here is the C# version: void cblFontStyle_Init(Object Source, EventArgs E) { string[] FontStyle = {"Underline","OverLine", "Strikeout"}; string[] Code = {"u","o","s"}; int i; for (i = 0; i < FontStyle.GetLength(0); i++) { this.cblFontStyle.Items.Add(new ListItem(FontStyle[i],Code[i])); } } Here is the VB.NET version: sub cblFontStyle_Init(ByVal Sender as Object, _ ByVal e as EventArgs) ' create arrays of items to add dim FontStyle( ) as string = {"Underline","OverLine", "Strikeout"} dim Code( ) as string= {"u","o","s"} dim i as integer for i = 0 to FontStyle.GetLength(0) -1 ' Add both Text and Value cblFontStyle.Items.Add(new ListItem(FontStyle(i),Code(i))) next end sub This code is very similar to Example 5-17 and Example 5-18. Here you create two string arrays, FontStyle and Code, to fill the ListItem properties Text and Value, respectively. The RadioButtonList control, on the other hand, does not have an onInit event handler, but rather the ListItems it contains are defined right within the control itself. This example uses self-closing ListItem tags with attributes specifying both the Text property and the Value property. In the case of the 12pt radio button, the Selected property is set to true, which makes this the default value on initialization. Notice that neither of these controls has any other event handler. Specifically, there is no event handler for OnSelectedIndexChanged, as there are in previous examples in this chapter. Yet, AutoPostBack is true. As you will see, the ASP Table control is rebuilt every time the page is loaded, which occurs every time either the CheckBoxList or the RadioButtonList control is changed. The current value for the font style is obtained from the CheckBoxList control, and the current font size is obtained from the RadioButtonList control. The ASP Table control is the heart of this page: <asp:Table id="tbl" backImageUrl="Sunflower Bkgrd.jpg" font-Name="Times New Roman" Font-Size="12" GridLines="Both" CellPadding="10" CellSpacing="5" HorizontalAlign="Left" Width="100%" runat="server"> <asp:TableRow> horizontalAlign="Left"> <asp:TableHeaderCell> Font Family </asp:TableHeaderCell> <asp:TableHeaderCell Width="80%"> Sample text </asp:TableHeaderCell> </asp:TableRow> </asp:Table> Like all ASP controls, the Table control inherits from WebControl and therefore has the standard set of properties, methods, and events from that class and the classes above it in the hierarchy. In addition, the Table control has properties of its own, which are listed in Table 5-12. Most of these properties are demonstrated in Example 5-29 and Example 5-30.
Note the following information about the ASP Table control in Example 5-29 and Example 5-30:
Nested inside the ASP Table control is a single ASP TableRow control. This row contains the header cells, as indicated by the fact that the ASP controls nested inside the TableRow control are ASP TableHeaderCell controls. 5.8.1 Table RowsThe ASP TableRow control is used to represent a single row in a Table control. It is derived from the WebControl class, just like the Table control. As Table 5-13 shows, it has only two properties that are not shared with all its other sibling controls.
5.8.2 Table CellsThere are two types of table cell ASP controls: a TableCell control for the body of the table and a TableHeaderCell for header cells. Both are used in Example 5-29 and Example 5-30. The ASP TableHeaderCell control represents a heading cell in a Table control. It is derived from the ASP TableCell control class. In fact, all of its properties, events, and methods are exactly the same as for the ASP TableCell control. The single difference between the TableCell and TableHeaderCell controls is that the TableHeaderCell control renders with a bold font, as can be seen in Figure 5-17. Notice that none of these nested TableHeaderCell controls in this example have either an id or a runat attribute. These attributes are not necessary here, since these controls are not accessed programmatically elsewhere in the code. Only a single row is defined statically. The rest of the rows are defined dynamically in the Page_Load method in the script block. In Example 5-29 and Example 5-30, the content of the header cells is the literal text strings between the opening and closing control tags. Alternatively, you may use self-closing tags and specify the content as a Text property: <asp:TableHeaderCell text="Font Family"/> The ASP TableCell control is used to contain the actual content of the table. Like the Table and TableRow controls, it is derived from the WebControl class. The TableCell and the TableHeaderCell controls have the properties shown in Table 5-14, which are not shared with its siblings.
You now have an ASP Table control containing a single TableRow object that contains a pair of TableHeaderCell objects. The script block's Page_Load method, which is run every time the page is loaded, creates the table dynamically. Often times, the Page_Load method will examine the IsPostBack property to test if the page is being loaded for the first time. If the load is the result of a postback, you may not want certain code to execute, either because it is both unnecessary and expensive, or because you will lose or change state information. In this example, however, you want the code to run every time the page loads. In fact, both the CheckBoxList and the RadioButtonList controls have their AutoPostBack properties set to true to force the page to post. This forces the table to be regenerated. Each time the table is regenerated, the font styles are obtained from the CheckBoxList control, and the font size is obtained from the RadioButtonList control. The Page_Load method begins by initializing a couple of variables. In C#, the code is: string str = "The quick brown fox jumped over the lazy dogs."; int i = 0; In VB.NET, the code is: dim str as string = "The quick brown fox jumped over the lazy dogs." dim i as integer = 0 str is the text displayed in the table, and i is a counter used later on. You get the style or styles from the CheckBoxList control. To do so, you initialize three Boolean variables to use as flags, one for each style. In C#, the code looks like: bool boolUnder = false; bool boolOver = false; bool boolStrike = false; In VB.NET, it looks like: dim boolUnder as Boolean = false dim boolOver as Boolean = false dim boolStrike as Boolean = false Then, using a for each loop to test each of the ListItem objects in the cblFontStyle CheckBoxList in turn, you set the variable for each font style to true if that checkbox has been selected. That is done by testing to see if the Selected property of the ListItem object is true. In C#, you might write: foreach(ListItem li in cblFontStyle.Items) { if (li.Selected == true) { switch (li.Value) { case "u": boolUnder = true; break; case "o": boolOver = true; break; case "s": boolStrike = true; break; } } } In VB.NET, you'd use: dim li as ListItem for each li in cblFontStyle.Items if li.Selected then select case li.Value case "u" boolUnder = true case "o": boolOver = true case "s": boolStrike = true end select end if next li Getting the font size selected in the RadioButtonList rblSize is much simpler, since all you have to do is get the Value property of the ListItem object returned by the SelectedItem property. You put that integer into the size variable. In C#, the code is: int size = Convert.ToInt32(rblSize.SelectedItem.Value); In VB.NET, it is: dim size as integer = Convert.ToInt32(rblSize.SelectedItem.Value) Now comes the meat of the method. You need to get a list of all the fonts installed on the machine. To do this, instantiate a new InstalledFontCollection object. In C#, the code is: InstalledFontCollection ifc = new InstalledFontCollection( ); In VB.NET, it is: dim ifc as InstalledFontCollection = new InstalledFontCollection( ) Iterate over that collection, using a for each loop, looking at each of the FontFamily objects in turn. In C#, you'd use: foreach( FontFamily ff in ifc.Families ) In VB.NET, the code is: dim ff as FontFamily for each ff in ifc.Families For each font family in the collection of FontFamilies, you create a new TableRow object. In C#, this looks like: TableRow r = new TableRow( ); In VB.NET, you'd have: dim r as TableRow = new TableRow( ) Within that TableRow object, you create two TableCell objects—one called cFont to hold the font name, and a second called cText to hold the sample text string defined earlier. In C#, the following code would suffice for the cFont cell: TableCell cFont = new TableCell( ); cFont.Controls.Add(new LiteralControl(ff.Name)); r.Cells.Add(cFont); In VB.NET, you'd use: dim cFont as TableCell = new TableCell( ) cFont.Controls.Add(new LiteralControl(ff.Name)) r.Cells.Add(cFont) The cFont TableCell object makes use of an ASP control called the LiteralControl. This control is used to insert text and HTML elements into the page. The only property of the LiteralControl, other than those inherited from Control, is the Text property. For the cell containing the sample text, you will use a slightly different technique, because you want to be able to manipulate the font and size properties of the text string. After instantiating a new TableCell object named cText, you also instantiate a Label control and assign the variable str, defined earlier, to its Text property. In C#, the code would be: TableCell cText = new TableCell( ); Label lbl = new Label( ); lbl.Text = str; In VB.NET, you'd use: dim cText as TableCell = new TableCell( ) dim lbl as Label = new Label( ) lbl.Text = str You increment the counter defined earlier and use it by assigning an ID property to the Label control. In C#, the following lines would work: i++; lbl.ID = "lbl" + i.ToString( ); In VB.NET, you'd use: i = i + 1 lbl.ID = "lbl" & i.ToString( ) Actually, this step is not necessary, because nowhere in this example do you actually need to refer back to any specific cell, but this was added to demonstrate how it can be done. You now assign the font name. In C#, this would look like: lbl.Font.Name = ff.Name; In VB.NET, it would look like: lbl.Font.Name = ff.Name Notice the syntax used here is different from the syntax for setting the font name within the tags of an ASP control (Font.Name versus Font-Name). Use the flags set earlier to set the font styles. In C#, the code is: if (boolUnder) lbl.Font.Underline = true; if (boolOver) lbl.Font.Overline = true; if (boolStrike) lbl.Font.Strikeout = true; In VB.NET, it is: if boolUnder then lbl.Font.Underline = true end if if boolOver then lbl.Font.Overline = true end if if boolStrike then lbl.Font.Strikeout = true end if Since the table is being re-created from scratch each time the page is loaded, and the defaults for each of these styles is no style (that is, false), there is no need to set the properties explicitly to false. Set the font size, add the TableCell object to the TableRow object, and add the TableRow object to the Table object. In C#, you'd use: lbl.Font.Size = size; cText.Controls.Add(lbl); r.Cells.Add(cText); tbl.Rows.Add(r); In VB.NET, you'd use: lbl.Font.Size = new FontUnit(size) cText.Controls.Add(lbl) r.Cells.Add(cText) tbl.Rows.Add(r) 5.8.3 Cell WidthControlling the width of the cells merits special mention. It is similar to controlling table width, but different enough to cause some confusion. Looking at the HTML portion of Example 5-29, you can see that the second cell in the header row has a Width attribute set to 80%: <asp:TableHeaderCell Width="80%"> Sample text </asp:TableHeaderCell> Browsers make all the cells in a column the same width. If none of the cells have any width specification, then the column will automatically size to best accommodate all the cells, taking into account any width specifications for the table and the size of the browser window. If multiple cells in a column have a width specification, then the widest cell specification is used. For easiest readability, it is usually best to include a width specification in only one row, generally the first row of the table. Hence, the Width attribute appears in the header row of this example. When the width is specified declaratively as part of an ASP control tag, it can be given either as a percentage of the entire table, as was done in this example, or it can be given as a fixed number of pixels, as in the following: Width="400"> Cell width can also be specified programmatically, in which case the syntax is somewhat different. Furthermore, the syntax differs between C# and VB.NET. Consider the lines of code from Example 5-29 and Example 5-30 that instantiate the cells containing the sample text, reproduced here for convenience. In C#, the code is: TableCell cText = new TableCell( ); In VB.NET, it is: Dim cText as TableCell = new TableCell( ) In either language, the variable cText, of type TableCell, is assigned to the cell instance. The Width property can be applied to this TableCell instance, either as pixels or a percentage of the table width. To specify the Width property as 80% of the table width, use the following line of code in C#: cText.Width = Unit.Percentage(80); Use this line of code in VB.NET: cText.Width = Unit.Percentage(80) To specify a fixed number of pixels, use either of the following lines of code in C#: cText.Width = Unit.Pixel(400); cText.Width = 400; In VB.NET, only this line of code will set the cell width to a fixed number of pixels: cText.Width = Unit.Pixel(400) There is an interaction between the cell Width property and the Wrap property. The default value for the Wrap property is true. If the Wrap property is set to false, one of the following situations will occur:
|
![]() ![]() |