Recipe 12.2 Creating Bar Charts on the Fly

     

Recipe 12.2 Creating Bar Charts on the Fly

12.2.1 Problem

You want to create a simple bar chart on the fly without having to resort to a commercial package to do so.

12.2.2 Solution

Use a combination of data binding with a Repeater control and the well-known HTML trick of stretching an image to create the bars.

In the .aspx file, add a Repeater control with an ItemTemplate .

In the code-behind class for the page, use the .NET language of your choice to:

  1. Assign the data source to the Repeater control and bind it.

  2. In the ItemDataBound event handler that is called for each item in the Repeater , set the width of the bar in the passed Repeater row.

Figure 12-2 shows some typical output. Examples Example 12-7 through Example 12-9 show the .aspx file and VB and C# code-behind files for an application that implements this solution.

Figure 12-2. Create bar chart output dynamically
figs/ancb_1202.gif

12.2.3 Discussion

This recipe provides a rather simple approach that combines data binding and HTML tricks to create a bar graph with very little coding, and without the need to purchase any additional components . By using more complex HTML, you can add more labels and other enhancements to this recipe, which may make it more useful for your situation.

The example we use to illustrate this solution generates a bar chart from chapter and problem data in a database. (The source of the data is not that important. Rather, it's the technique for generating the graph on the fly that is the main focus of this recipe.) The bar chart is created from an HTML table, with the top row used to label the chart.

This recipe advocates using a Repeater control to generate the rows in a table that represent the bars on the chart. The rows generated by the Repeater are defined in the ItemTemplate element, which in our example contains two columns . The first column is used to output the chapter number. In our example, the chapter number is obtained by binding the cell text to the Chapter column in the data source.

The second column contains the bar representing the number of problems in the chapter. The bar is created by using an HTML image tag with the source set to a 1-pixel-by-1-pixel image. The height and width attributes of the image "stretch" the image to the size of the bar needed to represent the number of problems in the chapter. In our example, the height is set to a fixed value of 15 pixels, but the width is adjusted to represent the number of problems in the chapter. The width is adjusted in the code-behind and is discussed later.

The second column also contains a label to indicate the actual number of problems in the chapter. The number of problems in a chapter is obtained by binding the cell text to the ProblemCount column in the data source. This label is placed at the end of the bar with a nonbreaking space (   ) to separate the label from the end of the bar.

The Page_Load method in the example code-behind reads the data from the database and then binds the data to the Repeater control on the page.

The code-behind class also implements the ItemDataBound event handler to provide the ability to adjust the width of the image used for the bar. The ItemDataBound event fires once per row in the Repeater as the row is data bound. In this event we need to get a reference to the HTML image in the row using the FindControl method of the row and then set the width of the image to reflect the number of problems in the chapter represented by the row.

If this recipe does not provide the richness you need for your chart, you can create an image using the concepts presented in Recipe 12.1. The System.Drawing classes provide all of the functionality to create very sophisticated charts using the GDI+. They do require considerably more coding, however, as you must build your graphs from the ground up using the basic ingredients of pen, brush, point, rectangle, and the like.

12.2.4 See Also

Recipe 12.1; MSDN Help for more information on the System.Drawing class

Example 12-7. Create bar chart dynamically (.aspx/.vb)
 <%@ Page Language="vb" AutoEventWireup="false"           Codebehind="CH12CreateChartVB.aspx.vb"           Inherits="ASPNetCookbook.VBExamples.CH12CreateChartVB" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html>   <head>     <title>Create Chart</title>     <link rel="stylesheet" href="css/ASPNetCookbook.css">   </head>   <body leftmargin="0" marginheight="0" marginwidth="0" topmargin="0">     <form id="frmTestDynamicChart" method="post" runat="server">       <table width="100%" cellpadding="0" cellspacing="0" border="0">         <tr>           <td align="center">             <img src="images/ASPNETCookbookHeading_blue.gif">           </td>         </tr>         <tr>           <td class="dividerLine">             <img src="images/spacer.gif" height="6" border="0"></td>         </tr>       </table>       <table width="90%" align="center" border="0">         <tr>           <td align="center">&nbsp;</td>         </tr>         <tr>           <td align="center" class="PageHeading">             Dynamic Chart Creation (VB)           </td>         </tr>         <tr>           <td><img src="images/spacer.gif" height="10" border="0"></td>         </tr>         <tr>           <td align="center">             <table border="2" bordercolor="#000080"  cellpadding="10">               <tr>                 <td>                   <table cellpadding="0" cellspacing="0" border="0">                     <tr>                       <td align="center" colspan="2" class="SubHeading">                         Problems Per Chapter<br /><br /></td>                     </tr>  <asp:Repeater ID="repChartBar" Runat="server">   <ItemTemplate>   <tr>   <td class="LabelText">   <%# DataBinder.Eval(Container.DataItem, "Chapter") %>&nbsp;   </td>   <td class="LabelText">   <img id="imgChartBar" runat="server"   src="images/blueSpacer.gif" border="0"   Height="15" align="middle" >   &nbsp;[<%# DataBinder.Eval(Container.DataItem, "ProblemCount") %>]   </td>   </tr>   </ItemTemplate>   </asp:Repeater>  </table>                 </td>               </tr>             </table>           </td>         </tr>       </table>     </form>   </body> </html> 

Example 12-8. Create bar chart dynamically code-behind (.vb)
 Option Explicit On  Option Strict On '----------------------------------------------------------------------------- ' '   Module Name: CH12CreateChartVB.aspx.vb ' '   Description: This module provides the code behind for the  '                CH12CreateChartVB.aspx page. ' '***************************************************************************** Imports Microsoft.VisualBasic Imports System Imports System.Configuration Imports System.Data Imports System.Data.Common Imports System.Data.OleDb Namespace ASPNetCookbook.VBExamples   Public Class CH12CreateChartVB     Inherits System.Web.UI.Page     'controls on the form     Protected WithEvents repChartBar As System.Web.UI.WebControls.Repeater     '***************************************************************************     '     '   ROUTINE: Page_Load     '     '   DESCRIPTION: This routine provides the event handler for the page load     '                event.  It is responsible for initializing the controls     '                on the page.     '---------------------------------------------------------------------------     Private Sub Page_Load(ByVal sender As System.Object, _                           ByVal e As System.EventArgs) Handles MyBase.Load       Dim dbConn As OleDbConnection       Dim dc As OleDbCommand       Dim dr As OleDbDataReader       Dim strConnection As String       Dim strSQL As String       If (Not Page.IsPostBack) Then         Try  'get the connection string from web.config and open a connection   'to the database   strConnection = _   ConfigurationSettings.AppSettings("dbConnectionString")   dbConn = New OleDb.OleDbConnection(strConnection)   dbConn.Open( )   'build the query string and get the data from the database   strSQL = "SELECT DISTINCT ChapterID AS Chapter, " & _   "count(*) AS ProblemCount " & _   "FROM Problem " & _   "GROUP BY ChapterID"   dc = New OleDbCommand(strSQL, dbConn)   dr = dc.ExecuteReader( )   'set the source of the data for the repeater control and bind it   repChartBar.DataSource = dr   repChartBar.DataBind( )  Finally           'cleanup           If (Not IsNothing(dbConn)) Then             dbConn.Close( )           End If         End Try       End If     End Sub     '***************************************************************************     '     '   ROUTINE: repChartBar_ItemDataBound     '     '   DESCRIPTION: This routine is the event handler that is called for each      '                item in the datagrid after a data bind occurs.  It is      '                responsible for setting the width of the bar in the      '                passed repeater row to reflect the number of problems in     '                the chapter the row represents     '---------------------------------------------------------------------------  Private Sub repChartBar_ItemDataBound(ByVal sender As Object, _   ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) _   Handles repChartBar.ItemDataBound   Dim img As System.Web.UI.HtmlControls.HtmlImage   'get a reference to the image used for the bar in the row   img = CType(e.Item.FindControl("imgChartBar"), _   System.Web.UI.HtmlControls.HtmlImage)   'set the width to the number of problems in the chapter for this row   'multiplied by a constant to stretch the bar a bit more   img.Width = _   CInt(CType(e.Item.DataItem, DbDataRecord)("ProblemCount")) * 10   End Sub  'repChartBar_ItemDataBound  End Class  'CH12CreateChartVB End Namespace 

Example 12-9. Create bar chart dynamically code-behind (.cs)
 //---------------------------------------------------------------------------- // //   Module Name: CH12CreateChartCS.aspx.cs // //   Description: This module provides the code behind for the  //                CH12CreateChartCS.aspx page // //**************************************************************************** using System; using System.Configuration; using System.Data; using System.Data.Common; using System.Data.OleDb; using System.Web.UI.WebControls; namespace ASPNetCookbook.CSExamples {   public class CH12CreateChartCS : System.Web.UI.Page   {     // controls on the form     protected System.Web.UI.WebControls.Repeater repChartBar;          //************************************************************************     //     //   ROUTINE: Page_Load     //     //   DESCRIPTION: This routine provides the event handler for the page      //                load event.  It is responsible for initializing the      //                controls on the page.     //------------------------------------------------------------------------     private void Page_Load(object sender, System.EventArgs e)     {       OleDbConnection dbConn = null;       OleDbCommand dc = null;       OleDbDataReader dr = null;       string strConnection = null;       String strSQL = null;       // bind the item data bound event       this.repChartBar.ItemDataBound +=          new RepeaterItemEventHandler(this.repChartBar_ItemDataBound);       if (!Page.IsPostBack)       {         try         {  // get the connection string from web.config and open a connection   // to the database   strConnection =   ConfigurationSettings.AppSettings["dbConnectionString"];   dbConn = new OleDbConnection(strConnection);   dbConn.Open( );   // build the query string and get the data from the database   strSQL = "SELECT DISTINCT ChapterID AS Chapter, " +   "count(*) AS ProblemCount " +   "FROM Problem " +   "GROUP BY ChapterID";   dc = new OleDbCommand(strSQL, dbConn);   dr = dc.ExecuteReader( );   // set the source of the data for the repeater control and bind it   repChartBar.DataSource = dr;   repChartBar.DataBind( );  }         finally         {           // clean up           if (dbConn != null)           {             dbConn.Close( );           }         }       }     }  // Page_Load     //************************************************************************     //     //   ROUTINE: repChartBar_ItemDataBound     //     //   DESCRIPTION: This routine is the event handler that is called for       //                each item in the datagrid after a data bind occurs.  It     //                is responsible for setting the width of the bar in the      //                passed repeater row to reflect the number of problems      //                in the chapter the row represents.     //------------------------------------------------------------------------  private void repChartBar_ItemDataBound(Object sender,   System.Web.UI.WebControls.RepeaterItemEventArgs e)   {   System.Web.UI.HtmlControls.HtmlImage img = null;   // get a reference to the image used for the bar in the row   img = (System.Web.UI.HtmlControls.HtmlImage)   (e.Item.FindControl("imgChartBar"));   // set the width to the number of problems in the chapter for this row   // multiplied by a constant to stretch the bar a bit more   img.Width =   (int)(((DbDataRecord)(e.Item.DataItem))["ProblemCount"]) * 10;   }  // repChartBar_ItemDataBound  }  // CH12CreateChartCS } 



ASP. NET Cookbook
ASP.Net 2.0 Cookbook (Cookbooks (OReilly))
ISBN: 0596100647
EAN: 2147483647
Year: 2006
Pages: 179

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