<asp:TemplateField> Control

GridView controls such as <asp:BoundField>, <asp:ImageField>, and <asp:HyperLinkField> can be used only to display a named data field from a data source. However, a GridView also can contain columns of data that do not appear in the data source. For instance, you may wish to include a column of calculated values. The displayed values are not contained in the data source, although they may be derived from fields in the data source. To display data values that are not data fields, an <asp:TemplateField> must be used. It also can be used in place of a BoundField, ImageField, or HyperLinkField to display information from a data source. Its general format is shown in Figure 7-12.

<asp:GridView id="id" Runat="Server"
  AutoGenerateColumns="False"
  ...>
	
  <Columns>
	
    <asp:TemplateField
      HeaderStyle-property="value"...
      ItemStyle-property="value"...
      FooterStyle-property="value"...
    >
			
      <HeaderTemplate>
        XHTML, text and server controls
      </HeaderTemplate>
		
      <ItemTemplate>
        XHTML, text and server controls
      </ItemTemplate>
		
      <AlternatingItemTemplate>
        XHTML, text and server controls
      </AlternatingItemTemplate>
		
      <FooterTemplate>
        XHTML, text and server controls
      </FooterTemplate>
		
    </asp:TemplateField>
    ...
	
  </Columns>
	
</asp:GridView>
Figure 7-12. General format for <asp:TemplateField> of <asp:GridView> control.

An <asp:TemplateField> appears inside the <Columns> tag of the GridView; it is composed of <HeaderTemplate>, <ItemTemplate>, <AlternatingItemTemplate>, and <FooterTemplate> tags enclosing text strings, XHTML tags, and server controls to format these areas of the column. Not all of these tags need to be coded, but you will need an <ItemTemplate> tag to display data values.

HeaderStyle, ItemStyle, and FooterStyle server stylings can be applied only through the <asp:TemplateField> control. They cannot be applied through the individual templates. You can, however, include CSS style sheets inside the templates to apply styles directly to enclosed text and XHTML elements.

In the following table, a calculated column gives the inventory amounts of selected books from the BooksDB.mdb database. A final footer line shows the total of these calculated amounts. The individual and total book amounts are not fields in the Books table, but they can be derived from fields in the table.

Inventory Valuation - Hardware Books
IDTitleBook DescriptionPriceQtyAmount
HW111How Computers Work
How Computers Work, 7th Edition, has been one of the bestselling computer books for the last 10 years. This four-color visual tutorial is a must-have for any computer user, from novice to expert. The rich graphics and intricate details about the inner workings of computers have been admired for years by consumers, instructors, professionals, and readers of all ages. A fresh cover and interior provide the reader with superior usability and it is the most aesthetically-pleasing edition yet!
$29.998 239.92
HW222Upgrading and Repairing PCs
Push your PC's performance to the limit. Know the differences between: Pentium II, Pentium MMX, Pentium Pro, and earlier CPU chips and choose the best chip for your needs; understand compatibility and feature sets of processor upgrade sockets, motherboards, and chipsets; use Universal Serial Bus ports and devices to simplify peripheral installation, configuration, and improve performance; squeeze the most performance, life, and reliability out of your hard drives; prevent memory headaches: pick the right speed and type of SIMMs and DIMMs, run more programs at once, and work with bigger files; and integrate hot new hardware including 3D graphics accelerators, fast SDRAM memory, Zoomed Video and CardBus PC Cards for your notebook, and NLX motherboards with support for Single Edge Contact processors and Accelerated Graphics Ports.
$59.995 299.95
HW333USB System Architecture
Universal Serial Bus System Architecture, Second Edition, based on the 2.0 version of the Universal Serial Bus specification, provides in-depth coverage and a detailed discussion of USB. It focuses on the USB protocol, signaling environment, and electrical specifications, along with the hardware/software interaction required to configure and access USB devices.
$49.991 49.99
HW444Designing Embedded Hardware
Designing Embedded Hardware is a book about designing small machines for embedded applications. There are many books on the market dedicated to writing code for particular microprocessors, or that stress the philosophy of embedded system design without providing any practical information. This book steers a middle path, telling you what you need to know to create your own products, and distilling much of the lore of embedded systems design into a single volume. It shows you how to build a complete embedded system, add peripherals, and connect your system to other devices.
$44.953 134.85
HW555Contemporary Logic Design
Contemporary Logic Design introduces a wide range of software tools including schematic capture, logic simulation, Boolean minimization, multi-level minimization and state assignment. Links the traditional techniques of logic design (such as Karnaugh maps and breadboard techniques) with real-world design examples. Provides comprehensive, early coverage of programmable logic including ROMs, PALs, and PLAs. Includes a variety of examples, exercises, problems, and case studies that illustrate real design problems and challenge the reader to develop practical solutions using modern design tools.
$102.952 205.90
    Total: $930.61

Figure 7-13. Using a Template column for calculated values in a GridView.

Binding Data Values to TemplateFields

A TemplateField, like a BoundField, can display values taken directly from a data source; it can also display calculated values involving data fields, and it can display values returned from function calls. In the case of binding a field from a data source to a TemplateField, the Eval() method is used as the equivalent of using a DataField property in a BoundField.

<%# Eval("fieldname") %>
Figure 7-14. General format for Eval() data binding method.

Code that appears between <%# and %> symbols is called a binding expression. The expression is replaced by its derived value. In the above format, the expression Eval("fieldname") evaluates to a value contained in a named field in a data source bound to the control.

Assume, for instance, that the BookPrice field from BooksDB.mdb were bound to and displayed in a TemplateField. The format for doing so would be similar to the following.

<asp:TemplateField>
	
  <HeaderTemplate>
    Price
  </HeaderTemplate>
	
  <ItemTemplate>
    <%# Eval("BookPrice") %>
  </ItemTemplate>
	
</asp:TemplateField>
Listing 7-8. Binding a data value to a GridView template.

The binding expression <%# Eval("BookPrice") %> is replaced by the actual data value of the BookPrice field for each row of the GridView that corresponds with a database record.

Although a binding expression itself can appear inside an ItemTemplate, it is often assigned to a server control to take advantage of the control's property settings. An alternative, and normally preferred, method of displaying a bound field is through the Text property of a Label control, as shown in the following recoding of the above TemplateField.

<asp:TemplateField
  HeaderText="Price">

  <ItemTemplate>
    <asp:Label Font-Name="Verdana" Font-Size="10pt" Runat="Server"
      Text='<%# Eval("BookPrice") %>'/>
  </ItemTemplate>
	
</asp:TemplateField>
Listing 7-9. Binding a data value to a GridView server control.

The value of the bound data item is displayed in the ItemTemplate as in the previous example. However, it also takes on any styling applied in the Label control through which it is displayed.

Note that the column heading is given by coding the HeaderText property for the TemplateField. This is an alternative to coding a separate <HeaderTemplate> tag as in the previous example.

Displaying Scrolling Fields

A GridView presents data fields along the rows of a table. Sometimes, though, the amount of data is too large to fit comfortably inside a table cell. In the above example, the BookDescription field is a case in point. If displayed in a BoundField, the size of the field expands vertically to encompass the amount of text being displayed, making for a very lengthy and awkward-looking table. A better solution is to display lengthy text fields inside scrollable fields all of the same dimensions, as is done in the example.

A TemplateField can include a Label control inside a Panel control to create a scrollable field. The Panel is given Width and Height settings for the fixed size of the display area, along with the ScrollBars property to introduce scroll bars. Text is bound to the Label control inside this scrollable area. Below is shown code for the TemplateField used to display book descriptions in the example GridView.

<asp:TemplateField
  HeaderText="Book Description">
  <ItemTemplate>
    <asp:Panel Width="230px" Height="40px" ScrollBars="Vertical" 
    Runat="Server">
      <asp:Label Font-Size="8pt" Font-Name="Verdana"
      Text='<%# Eval("BookDescription") %>' Runat="Server"/>
    </asp:Panel>
  </ItemTemplate>
</asp:TemplateField>
Listing 7-10. Creating scrollable text in a GridView column.

In the current example, ScrollBars is set to "Vertical" to always display a vertical scroll bar whether needed or not to display the enclosed text. An option is to set this property to "Auto" to display a vertical scroll bar only if needed.

Binding Calculated Values

If data values for template columns are not taken directly from a data source, then scripting is needed to supply these values. In the example GridView, the final column displays the calculated value of the BookPrice field multiplied times the BookQty field. One of the ways to supply these values is by including this calculation inside a binding expression as shown by the following code.

<asp:TemplateField
  HeaderText="Amount"
  ItemStyle-HorizontalAlign="Right">

  <ItemTemplate>
    <asp:Label Text='<%# Eval("BookPrice") * Eval("BookQty") %>' 
    Runat="Server"/>
  </ItemTemplate>

</asp:TemplateField>
Listing 7-11. Binding calculated expressions to a GridView.

For each row of the GridView, the BookPrice field from the database row is multiplied by the BookQty field, and the resulting value is bound to the ItemTemplate's enclosed Label. Formatting can be applied to the calculated amount—to the binding expression—using either

Text='<%# FormatNumber(Eval("BookPrice") * Eval("BookQty"), 2) %>'
or
Text='<%# String.Format("{0:N2}", Eval("BookPrice") * Eval("BookQty")) %>'

Binding Functions

A second method to supply a calculated value for a TemplateField is to bind a value returned from a Visual Basic function call. The function call appears inside a binding expression and is replaced by its returned value. An alternative, for example, to including the above multiplication itself inside a binding expression is to move the calculation to a function call and pass to it the BookPrice and BookQty values to be multiplied.

Function Get_Amount (Price As Decimal, Quantity As Integer)

  Dim Amount As Decimal = Price * Quantity
  Return String.Format("{0:N2}", Amount)

End Function


<asp:TemplateField
  HeaderText="Amount"
  ItemStyle-HorizontalAlign="Right">
	
  <ItemTemplate>
    <asp:Label Text='<%# Get_Amount(Eval("BookPrice"), Eval("BookQty")) %>' 
    Runat="Server"/>
  </ItemTemplate>
	
</asp:TemplateField>
Listing 7-12. Binding functions to a GridView.

For each row of the GridView, the BookPrice and BookQty values are passed to the Get_Amount() function. The function returns variable Amount, whose calculated and formatted value is displayed in the binding expression as replacement for the function call.

In the example GridView, not only does the final column display a calculated value for a row, but the FooterTemplate displays the total of all calculated amounts. Therefore, two Visual Basic functions are used. The Get_Amount() function is an expansion of the one above in order to accumulate the calculated amount; the Get_Total() function returns the final accumulated inventory total. The full script and GridView code for this application are shown below.

<SCRIPT Runat="Server">

Dim Total As Decimal = 0.00

Function Get_Amount (Price As Decimal, Quantity As Integer)

  Dim Amount As Decimal = Price * Quantity
  Total += Amount
  Return String.Format("{0:N2}", Amount)

End Function

Function Get_Total()

  Return String.Format("{0:C}", Total)

End Function

</SCRIPT>

<form Runat="Server">

<asp:AccessDataSource id="BookSource" Runat="Server"
  DataFile="../Databases/BooksDB.mdb"
  SelectCommand="SELECT * FROM Books WHERE BookType='Hardware' 
                 ORDER BY BookID"/>
	
<asp:GridView id="BookGrid" DataSourceID="BookSource" Runat="Server"
  AutoGenerateColumns="False"
  ShowFooter="True"
  Caption="<b>Inventory Valuation - Hardware Books</b>"
  CellPadding="3"
    HeaderStyle-BackColor="#707070"
    HeaderStyle-ForeColor="#FFFFFF"
    RowStyle-Font-Name="Verdana"
    RowStyle-Font-Size="8pt"
    RowStyle-VerticalAlign="Top"
    FooterStyle-BackColor="#707070"
    FooterStyle-ForeColor="#FFFFFF"
    FooterStyle-Font-Size="11pt">

  <Columns>
	
  <asp:BoundField
    DataField="BookID"
    HeaderText="ID"
    FooterStyle-BorderWidth="0"/>

  <asp:BoundField
    DataField="BookTitle"
    HeaderText="Title"
    FooterStyle-BorderWidth="0"/>
	
  <asp:TemplateField
    HeaderText="Book Description">
    <ItemTemplate>
      <asp:Panel Width="230px" Height="40px" ScrollBars="Vertical" 
      Runat="Server">
        <asp:Label Font-Size="8pt" Font-Name="Verdana" Runat="Server"
        Text='<%# Eval("BookDescription") %>'/>
      </asp:Panel>
    </ItemTemplate>
  </asp:TemplateField>

  <asp:BoundField
    DataField="BookPrice"
    HeaderText="Price"
    ItemStyle-HorizontalAlign="Right"
    HtmlEncode="False"
    DataFormatString="{0:N2}"
    FooterStyle-BorderWidth="0"/>

  <asp:BoundField
    DataField="BookQty"
    HeaderText="Qty"
    ItemStyle-HorizontalAlign="Right"
    HtmlEncode="False"
    DataFormatString="{0:D}"
    FooterText="Total: "
    FooterStyle-Font-Bold="True"
    FooterStyle-BorderWidth="0"/>
		
  <asp:TemplateField
    HeaderText="Amount"
    ItemStyle-HorizontalAlign="Right"
    FooterStyle-Font-Size="10pt"
    FooterStyle-HorizontalAlign="Right"
    FooterStyle-Font-Bold="True"
    FooterStyle-BorderWidth="0">
    <ItemTemplate>
      <asp:Label id="Amount" Runat="Server"
        Text='<%# Get_Amount(Eval("BookPrice"), Eval("BookQty")) %>'/>
    </ItemTemplate>
    <FooterTemplate>
      <asp:Label id="Total" Runat="Server"
        Text='<%# Get_Total() %>'/>
    </FooterTemplate>
  </asp:TemplateField>
	
  </Columns>

</asp:GridView>
Listing 7-13. Code for example GridView with calculated columns.

BoundField columns are used to display the BookID, BookTitle, BookPrice, and BookQty fields directly from the available recordset. A TemplateField is needed for the amount column, which displays the price field multiplied times the quantity field for each record. Also, this calculated amount is summed to derive the total inventory value reported in the footer row of the column.

A global variable named Total is declared and initialized at the beginning of the script. This variable serves as an accumulator for the inventory total. Function Get_Amount() is passed two values, a price and a quantity from the associated database record; these values are received by the function through its argument list.

Within function Get_Amount(), the received Price and Quantity values are multiplied to derive local variable Amount. This amount is added to global variable Total prior to returning it to the calling expression for display. Recall that a function call is replaced by a returned value; therefore, the Amount value is substituted for the calling statement. The numeric format string is applied to the returned Amount to style it for display. As you can see, variable Total is necessarily a global variable. It cannot be declared inside function Get_Amount() or it would be reinitialzed on each call and never accumulate the calculated Amounts.

This processing is repeated for each of the database records in the data source. At the end of processing, a footer row is added to the table to report the inventory Total, which was accumulating with each function call to Get_Amount(). The function call to Get_Total() simply returns the currency-formatted value of variable Total, replacing the call with the inventory total.

Incidentally, it is not necessary to call function Get_Total() to display variable Total. Any global script variable can be bound to a template simply by enclosing the variable name in a binding expression. Alternate coding for the above FooterTemplate is shown below.

<FooterTemplate>
  <asp:Label Text='<%# String.Format("{0:C}", Total) %>' Runat="Server"/>
</FooterTemplate>
Listing 7-14. Binding a variable to a GridView template.

You might notice in the example GridView that the footer row does not contain borders between columns, leaving the impression that the footer is a single cell that spans the width of the table. This is not the case, however. Separate columns still appear and cannot, in fact, be spanned. The effect is produced by setting the BorderWidth property of all footer columns to 0 pixels: FooterStyle-BorderWidth="0".

Displaying Pictures in Templates

A TemplateField can be used to display graphic images in a GridView column. In the following example, an <asp:Image> control is coded inside an <ItemTemplate> and is bound to a reference to an image file. In addition, an <asp:HyperLink> control appears in the template to open the full-size image in a separate frame.


IDTitlePricePicture
GR111Adobe Photoshop CS2$29.99 Picture of GR111
Full Size
GR222Learning Web Design$39.95 Picture of GR222
Full Size
GR333Macromedia Flash Professional$44.99 Picture of GR333
Full Size
GR444Digital Photographer Handbook$24.95 Picture of GR444
Full Size
GR555Creating Motion Graphics$59.95 Picture of GR555
Full Size
  

Figure 7-15. Using a Template column to display images and links in a GridView.
<asp:AccessDataSource id="BookSource" Runat="Server"
  DataFile="../Databases/BooksDB.mdb"
  SelectCommand="SELECT BookID, BookTitle, BookPrice FROM Books
                 WHERE BookType='Graphics' ORDER BY BookID"/>

<asp:GridView id="BookGrid" DataSourceID="BookSource" Runat="Server"
  AutoGenerateColumns="False"
  Style="float:left"
  CellPadding="3"
    HeaderStyle-BackColor="#707070"
    HeaderStyle-ForeColor="#FFFFFF"
    HeaderStyle-Font-size="11pt"
    RowStyle-VerticalAlign="Top"

  <Columns>
	
  <asp:BoundField
    DataField="BookID"
    HeaderText="ID"/>
	
  <asp:BoundField
    DataField="BookTitle"
    HeaderText="Title"/>
	
  <asp:BoundField
    DataField="BookPrice"
    HeaderText="Price"
    ItemStyle-HorizontalAlign="Right"
    DataFormatString="{0:N2}"/>

  <asp:TemplateField
    HeaderText="Picture"
    ItemStyle-Font-Size="9pt"
    ItemStyle-HorizontalAlign="Center">
    <ItemTemplate>
      <asp:Image Width="40" Runat="Server"
        AlternateText='<%# "Picture of " & Eval("BookID") %>'
        ImageUrl='<%# "../BookPictures/" & Eval("BookID") & ".jpg" %>'/><br/>
      <asp:HyperLink Text="Full Size" Target="PictureFrame" Runat="Server"
        NavigateUrl='<%# "../BookPictures/" & Eval("BookID") & ".jpg" %>'/>
    </ItemTemplate>
  </asp:TemplateField>

  </Columns>

</asp:GridView>

<iframe name="PictureFrame" style="width:130px; height:160px; 
border:outset 5"></iframe>
Listing 7-15. Code for Template column to display images and links.

Recall from an earlier example that use of an <asp:ImageField> control in a GridView does not permit resizing of the image. However, using an <asp:Image> control in a TemplateField does permit its resizing during display. In this case, its Width is set at 40 pixels with its height adjusted automatically to maintain proportionality. An accompanying <asp:HyperLink> control appears below the image to display clickable text to open the full-size picture in a floating frame.

Since book pictures have names matching their BookIDs, their directory path concatenated with the BookID concatenated with the string ".jpg" produces the URL for the associated picture. The ImageUrl property of the <asp:Image> control and the NavigateUrl property of the <asp:HyperLink> control are binding expressions using this URL, the former to display the picture and the latter to target it to the <iframe>. The AlternateText property of the Image control includes a binding expression to the BookID for its display as alternate text on mouse-over of the image.