[ Team LiB ] |
16.3 Displaying the OutputYour ASP.NET application is pretty straightforward. The .aspx file for the web form is shown in Example 16-3. Example 16-3. Displaying the output<%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="SalesDisplay.Sales" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" > <html> <head> <title>WebForm1</title> <meta name="GENERATOR" Content="Microsoft Visual Studio 7.0"> <meta name="CODE_LANGUAGE" Content="C#"> <meta name=vs_defaultClientScript content="JavaScript"> <meta name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5"> </head> <body MS_POSITIONING="GridLayout"> <form id="SalesReport" method="post" runat="server" title="Sales Report"> <asp:Label ID="lblMsg" Runat="server"> The data found here is screen scraped from Amazon and stored in a local database. The data is updated every 15 minutes. This is a work in progress. </asp:Label><br> Last Updated: <asp:Label id="lblLastUpdate" Runat="server" text="<%# lastUpdate %>" /> Show <asp:TextBox id=txtShowRecords Runat="server" AutoPostBack="True" Width="20" text="<%# showRecords %>" /> Records <br><br> <b>ASP Titles</b> <asp:DataGrid id="dgASPSalesRank" CellPadding="5" OnItemDataBound="Item_Bound" AutoGenerateColumns="False" HeaderStyle-BackColor="PapayaWhip" BorderColor="#000099" AlternatingItemStyle-BackColor="LightGrey" HeaderStyle-Font-Bold=true Width="900" runat="server"> <columns> <asp:templatecolumn HeaderStyle-Width ="10"> <headertemplate> Position </headertemplate> <itemtemplate> <asp:label text="<%# rowNumber %>" runat="server" ID="Label1"/> </itemtemplate> </asp:templatecolumn> <asp:templatecolumn> <headertemplate> Title </headertemplate> <itemtemplate> <a href="http://www.amazon.com/exec/obidos/ASIN/<%# DataBinder.Eval(Container. DataItem, "isbn") %>/" target="_blank"><%# DataBinder.Eval(Container.DataItem, "title") %> </a> </itemtemplate> </asp:templatecolumn> <asp:BoundColumn HeaderText="Author" ReadOnly="true" DataField="author"/> <asp:BoundColumn HeaderText="Publisher" ReadOnly="true" DataField="publisher"/> <asp:BoundColumn HeaderText="Publish Date" ReadOnly="true" DataField="pubdate"/> <asp:BoundColumn HeaderText="Rank" ReadOnly="true" DataField="Rank" DataFormatString="{0:N0}" ItemStyle-HorizontalAlign="Right"/> </columns> </asp:DataGrid> <br> <br><hr><br> <b>C# Titles</b> <asp:DataGrid id="dgCSharpSalesRank" CellPadding="5" OnItemDataBound="Item_Bound" AutoGenerateColumns="False" HeaderStyle-BackColor="PapayaWhip" BorderColor="#000099" AlternatingItemStyle-BackColor="LightGrey" HeaderStyle-Font-Bold=true Width="900" runat="server"> <columns> <asp:templatecolumn HeaderStyle-Width ="10"> <headertemplate> Position </headertemplate> <itemtemplate> <asp:label text="<%# rowNumber %>" runat="server" ID="Label2"/> </itemtemplate> </asp:templatecolumn> <asp:templatecolumn> <headertemplate> Title </headertemplate> <itemtemplate> <a href="http://www.amazon.com/exec/obidos/ASIN/<%# DataBinder.Eval(Container. DataItem, "isbn") %>/" target="_blank"><%# DataBinder.Eval(Container.DataItem, "title") %> </a> </itemtemplate> </asp:templatecolumn> <asp:BoundColumn HeaderText="Author" ReadOnly="true" DataField="author"/> <asp:BoundColumn HeaderText="Publisher" ReadOnly="true" DataField="publisher"/> <asp:BoundColumn HeaderText="Publish Date" ReadOnly="true" DataField="pubdate"/> <asp:BoundColumn HeaderText="Rank" ReadOnly="true" DataField="Rank" DataFormatString="{0:N0}" ItemStyle-HorizontalAlign="Right"/> </columns> </asp:DataGrid> <br> <br><hr><br> <b>VB.NET Titles</b> <asp:DataGrid id="dgVBNETSalesRank" CellPadding="5" OnItemDataBound="Item_Bound" AutoGenerateColumns="False" HeaderStyle-BackColor="PapayaWhip" BorderColor="#000099" AlternatingItemStyle-BackColor="LightGrey" HeaderStyle-Font-Bold=true Width="900" runat="server"> <columns> <asp:templatecolumn HeaderStyle-Width ="10"> <headertemplate> Position </headertemplate> <itemtemplate> <asp:label text="<%# rowNumber %>" runat="server" ID="Label3"/> </itemtemplate> </asp:templatecolumn> <asp:templatecolumn> <headertemplate> Title </headertemplate> <itemtemplate> <a href="http://www.amazon.com/exec/obidos/ASIN/<%# DataBinder.Eval(Container. DataItem, "isbn") %>/" target="_blank"><%# DataBinder.Eval(Container.DataItem, "title") %> </a> </itemtemplate> </asp:templatecolumn> <asp:BoundColumn HeaderText="Author" ReadOnly="true" DataField="author"/> <asp:BoundColumn HeaderText="Publisher" ReadOnly="true" DataField="publisher"/> <asp:BoundColumn HeaderText="Publish Date" ReadOnly="true" DataField="pubdate"/> <asp:BoundColumn HeaderText="Rank" ReadOnly="true" DataField="Rank" DataFormatString="{0:N0}" ItemStyle-HorizontalAlign="Right"/> </columns> </asp:DataGrid> <br> <br> <br><hr><br> <b>All Titles</b> <asp:DataGrid id="dgAll" CellPadding="5" OnItemDataBound="Item_Bound" AutoGenerateColumns="False" HeaderStyle-BackColor="PapayaWhip" BorderColor="#000099" AlternatingItemStyle-BackColor="LightGrey" HeaderStyle-Font-Bold=true Width="900" runat="server"> <columns> <asp:templatecolumn HeaderStyle-Width ="10"> <headertemplate> Position </headertemplate> <itemtemplate> <asp:label text="<%# rowNumber %>" runat="server" ID="Label4"/> </itemtemplate> </asp:templatecolumn> <asp:templatecolumn> <headertemplate> Title </headertemplate> <itemtemplate> <a href="http://www.amazon.com/exec/obidos/ASIN/<%# DataBinder.Eval(Container. DataItem, "isbn") %>/" target="_blank"><%# DataBinder.Eval(Container.DataItem, "title") %> </a> </itemtemplate> </asp:templatecolumn> <asp:BoundColumn HeaderText="Author" ReadOnly="true" DataField="author"/> <asp:BoundColumn HeaderText="Publisher" ReadOnly="true" DataField="publisher"/> <asp:BoundColumn HeaderText="Publish Date" ReadOnly="true" DataField="pubdate"/> <asp:BoundColumn HeaderText="Rank" ReadOnly="true" DataField="Rank" DataFormatString="{0:N0}" ItemStyle-HorizontalAlign="Right"/> </columns> </asp:DataGrid> <br> <br> </form> </body> </html> The key aspect of the HTML is the creation of three data grids. They each work the same way, so we'll focus on the first,: <asp:DataGrid id="dgASPSalesRank" CellPadding="5" OnItemDataBound="Item_Bound" AutoGenerateColumns="False" HeaderStyle-BackColor="PapayaWhip" BorderColor="#000099" AlternatingItemStyle-BackColor="LightGrey" HeaderStyle-Font-Bold=true Width="900" runat="server"> The data grid is named dgASPSalesRank. A few properties are set, the most important of which is the event handler for the OnItemDataBound event and the Boolean property AutoGenerateColumns, which is set to False. This allows you to take direct control of the columns, which you do by creating a columns element: <columns> ... </columns> The first column within the columns element is a template column element. A template column allows you to insert controls into the column. In the first instance, you'll insert a headertemplate (used to create a column header) with the text Position, and an asp:label control. That label will display, as its text, a row number. The mechanism for generating this row number is discussed in "Handling The Item_Bound Event," later in this chapter. <asp:templatecolumn HeaderStyle-Width ="10"> <headertemplate> Position </headertemplate> <itemtemplate> <asp:label text="<%# rowNumber %>" runat="server" ID="Label1"/> </itemtemplate> </asp:templatecolumn>
The second column is also a template column, this time with the column heading Title. The title itself is displayed by evaluating the title column in the current row in the data set to which this data grid is bound, and surrounding that title with a link to the appropriate page on Amazon.com. This makes the title a hyperlink the user can click on. <asp:templatecolumn> <headertemplate> Title </headertemplate> <itemtemplate> <a href="http://www.amazon.com/exec/obidos/ASIN/ <%# DataBinder.Eval(Container.DataItem, "isbn") %>/" target="_blank"><%# DataBinder.Eval(Container.DataItem, "title") %></a> </itemtemplate> </asp:templatecolumn> Let's take this apart. The first element is the template column: <asp:templatecolumn> </asp:templatecolumn> Within the template column are two template elements: the header and the item. The header is pretty straightforward. It has simple text (though it could have any kind of HTML): <headertemplate> Title </headertemplate> The item template is a bit trickier: <itemtemplate> <a href="http://www.amazon.com/exec/obidos/ASIN/ <%# DataBinder.Eval(Container.DataItem, "isbn") %>/" target="_blank"><%# DataBinder.Eval(Container.DataItem, "title") %></a> </itemtemplate> This one we'll evaluate from the outside in. The first thing to notice is the start of a normal hyperlink: <a href="http://www.amazon.com/exec/obidos/ASIN/ However, the hyperlink is then appended with the result of evaluating the ISBN from the bound data: <%# DataBinder.Eval(Container.DataItem, "isbn") %>/" This hyperlink tag has an attribute: target="_blank" that causes the link to open a new instance of the browser. The body of the link (the displayed text of the link) is also an evaluated value: DataBinder.Eval(Container.DataItem, "title") If the bound data has the title Programming Visual Basic .NET, Second Edition and the ISBN 0596004389, this item will emit the following HTML: <a href=http://www.amazon.com/exec/obidos/ASIN/0596004389/ target="_blank"> Programming Visual Basic .NET 2nd Edition </a> The first two columns are tricky. The first because we need to do some work to create the rowNumber (see the code that follows), and the second because we need to wrap the bound value (the ISBN and the title) inside a hyperlink. The next four columns are easier; they are just bound to the data. The first bound column has the header text Author, is marked as readOnly and is bound to the author column in the row of the data set table to which this data grid is bound: <asp:BoundColumn HeaderText="Author" ReadOnly="true" DataField="author"/> Notice that this is a self-closing element, as are the next three bound columns: <asp:BoundColumn HeaderText="Publisher" ReadOnly="true" DataField="publisher"/> <asp:BoundColumn HeaderText="Publish Date" ReadOnly="true" DataField="pubdate"/> <asp:BoundColumn HeaderText="Rank" ReadOnly="true" DataField="Rank" DataFormatString="{0:N0}" ItemStyle-HorizontalAlign="Right"/> 16.3.1 Implementing the GridThe complete source code for the code-behind is shown in Example 16-4, followed by the analysis. Example 16-4. Code-behind file for SalesDisplayusing System; using System.Collections; using System.ComponentModel; using System.Data; using System.Data.SqlClient; using System.Drawing; using System.Web; using System.Web.SessionState; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.HtmlControls; namespace SalesDisplay { public class Sales : System.Web.UI.Page { protected System.Web.UI.WebControls.DataGrid dgASPSalesRank; protected System.Web.UI.WebControls.DataGrid dgCSharpSalesRank; protected System.Web.UI.WebControls.DataGrid dgVBNETSalesRank; protected System.Web.UI.WebControls.DataGrid dgAll; protected System.Web.UI.WebControls.Label lblMsg; protected System.Web.UI.WebControls.Label lblLastUpdate; protected System.Web.UI.WebControls.TextBox txtShowRecords; protected int rowNumber = 0; protected int showRecords; protected int totalASP; protected int totalCSharp; protected string lastUpdate; private void Page_Load(object sender, System.EventArgs e) { // initialize number of records to show to 7 if (! IsPostBack ) { showRecords = 7; } // if it is a post back, get the number // from the text box else { showRecords = Convert.ToInt32(txtShowRecords.Text); } // connect to the db string connectionString = "server=localhost;Trusted_Connection=true;database=AmazonSalesRanks"; // pick records to display string commandString = @"Select top " + showRecords + " * from BookInfo where technology = 'ASPNET' order by rank"; SqlDataAdapter dataAdapter = new SqlDataAdapter(commandString, connectionString); DataSet dataSet = new DataSet( ); dataAdapter.Fill(dataSet,"aspBookInfo"); // first table commandString = @"Select top " + showRecords + " * from BookInfo where technology = 'CSHARP' order by rank"; dataAdapter = new SqlDataAdapter(commandString, connectionString); dataAdapter.Fill(dataSet,"csBookInfo"); // second table commandString = @"Select top " + showRecords + " * from BookInfo where technology = 'VBNET' order by rank"; dataAdapter = new SqlDataAdapter(commandString, connectionString); dataAdapter.Fill(dataSet,"vbBookInfo"); // third table // create the data view and bind to the grid DataView aspDataView = dataSet.Tables[0].DefaultView; dgASPSalesRank.DataSource = aspDataView; dgASPSalesRank.DataBind( ); rowNumber = 0; DataView csDataView = dataSet.Tables[1].DefaultView; dgCSharpSalesRank.DataSource = csDataView; dgCSharpSalesRank.DataBind( ); rowNumber = 0; DataView vbDataView = dataSet.Tables[2].DefaultView; dgVBNETSalesRank.DataSource = vbDataView; dgVBNETSalesRank.DataBind( ); // get the last update time from the last table lastUpdate = dataSet.Tables[2].Rows[0]["lastUpdate"].ToString( ); txtShowRecords.DataBind( ); lblLastUpdate.DataBind( ); } // each time data is bound, update the row number // to provide relative rankings public void Item_Bound(Object sender, DataGridItemEventArgs e) { rowNumber++; } #region Web Form Designer generated code #endregion } } The program begins by declaring a number of local variables, the most important of which is the rowNumber, which is initialized to zero: protected int rowNumber = 0; The showRecords member variable is used to keep track of how many records to display, and when the page is first displayed that is set to 7. On subsequent postbacks of the page, that value is set to whatever is in the text box: private void Page_Load(object sender, System.EventArgs e) { if (! IsPostBack ) { showRecords = 7; } else { showRecords = Convert.ToInt32(txtShowRecords.Text); } Continuing in the page-load event handler, the database connection is made and the database is searched, based on the "technology" (i.e., ASPNET versus C# versus VBNET). string connectionString = "server=localhost;Trusted_Connection=true;database=AmazonSalesRanks"; string commandString = @"Select top " + showRecords + " * from BookInfo where technology = 'ASPNET' order by rank"; SqlDataAdapter dataAdapter = new SqlDataAdapter(commandString, connectionString); DataSet dataSet = new DataSet( ); dataAdapter.Fill(dataSet,"aspBookInfo"); // first table The same is done for each of the other queries. Once the tables in the data set are created, a data view is created for the first table. This represents a view of the ASPNET results: DataView aspDataView = dataSet.Tables[0].DefaultView; It is to this data view that the data grid is bound: dgASPSalesRank.DataSource = aspDataView; dgASPSalesRank.DataBind( ); Once this is done, the rowNumber member variable is set back to zero (we'll discuss how it moves from zero below), and the next data view is created and bound to its respective data grid: rowNumber = 0; DataView csDataView = dataSet.Tables[1].DefaultView; dgCSharpSalesRank.DataSource = csDataView; dgCSharpSalesRank.DataBind( ); This is done one final time for the third table: rowNumber = 0; DataView vbDataView = dataSet.Tables[2].DefaultView; dgVBNETSalesRank.DataSource = vbDataView; dgVBNETSalesRank.DataBind( ); Finally, the lastUpdate member variable is set from the lastUpdate field in the table, and the text box and label are bound: txtShowRecords.DataBind( ); lblLastUpdate.DataBind( ); 16.3.2 Handling the Item_Bound EventYou will remember that when you created the data grid, you bound the OnItemDataBound event to the Item_Bound method. As a matter of fact, you did this for all three data grids. Whenever an item is bound on any grid, it is handled in this method. All the method does is to increment the row counter, rowNumber. public void Item_Bound(Object sender, DataGridItemEventArgs e) { rowNumber++; } The net effect is that each time an item is bound to the data grid, the rowNumber is incremented and then displayed in the first templated column, giving you a relative ranking within the data grid. |
[ Team LiB ] |