A Google Chart API Custom Server Control
By Scott Mitchell
Introduction
Last week's article, Creating Charts with the Google Chart API, looked at how
to use Google's free Chart API to generate line, pie, bar, and other types of charts from an ASP.NET page. The Google Chart API is callable via a
URL that contains the chart type, size, data, and other parameters in the querystring and returns the chart as an image. Displaying a chart
using this API is as simple as adding an Image Web control to a page and setting its ImageUrl property to the Google Chart API URL with
an appropriately formatted querystring.
Last week's article explored the essential querystring parameters and provided an example on how to programmatically
construct this querystring to plot data from a database query. In a nutshell, constructing this querystring involved about 50 lines of code
to get the data, express the data as percentages relative to one another, and build up the other parameters. Wouldn't it be much easier if we could
create a chart by dropping a Google Chart API Web control on the page, set a few properties, and then bind it to a data source control, like a
SqlDataSource or ObjectDataSource? That way we could create and display charts using the Google Chart API without having to write a lick of code.
Over the past week I built such a Web control. The Web control does not provide the full suite of Google Chart API features - it only allows for the
creation of line, bar, and pie charts, and it only allows a single data series - but it makes creating and displaying data-driven charts as easy as
drag-and-drop and point-and-click. This article shows how to use this free custom server control and highlights some of its more interesting aspects.
You can download the compiled server control, its complete source code, and a demo application at the end of this article. Read on to learn more!
First Things First: Read Creating Charts with the Google Chart API
Before tackling this article I encourage you to first read last week's article, Creating Charts with
the Google Chart API. This article assumes you are already familiar with the Google Chart API, how the chart data is formatted, and some of the
germane querystring parameters used in creating the chart.
An Overview of the Chart Control in the skmControls2 Library
After writing last week's article, in which I wrote 50+ lines of code that showed how to use Google Chart API to display a chart based on database data,
I decided there had to be an easier way to show a simple chart. Ideally, a developer could drag a chart control from the Toolbox onto an ASP.NET page,
set a few properties to indicate things like the chart type, size, and color, and then specify the chart's data in a number of different ways:
By binding the chart to a data source control, such as a SqlDataSource or ObjectDataSource control,
Specifying hard-coded chart data statically in the page's markup, or
Specifying the chart data programmatically
A number of built-in ASP.NET Web controls implement this pattern. For instance, the DropDownList control has a variety of properties that can be used
to specify its appearance, and the data displayed in the DropDownList can be specified statically, programmatically, or from a data source control.
I wanted to build a similar control, but instead of emitting a drop-down list the control would instead output an <img> element with
its src attribute set to the appropriate URL to generate the chart with the given data.
I created a custom server control named Chart that is part of my skmControls2 library, a collection of custom server controls for ASP.NET version 2.0
and up. Other controls in the skmControls2 library include an enhanced GridView control,
a data bound Label control, and a TextBox
word and character counter control. You can download the latest version of the skmControls2 library, along with a demo application, at the end of
this article.
The Chart control is used in the following manner: a page developer adds the Chart control to an ASP.NET page. She can then configure appearance-related
properties like ChartType, Height, Width, LineColor, ChartTitle, and others.
Next, the page developer would specify the chart's data as a series of data points. Each data point has two attributes:
Value - the data point value
Label - the text label associated with the data point
This series of data points is stored in the Chart control's Items collection. The values of the Items collection can be
expressed in three different ways:
Statically - you can specify the data points through the declarative markup of the Chart control. For instance, to create a chart with
data points labeled Q1, Q2, Q3, and Q4 with values 45, 21, 88, and 34, respectively, you could use the following declarative markup:
Programmatically - the Items collection is a collection of objects of type DataPoint. You can programmatically
create these objects and add them to Items. Here's a snippet of code that adds the four data points shown above, but does so programmatically
rather than statically.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
DynamicChart.Items.Add(New DataPoint("45", "Q1"))
DynamicChart.Items.Add(New DataPoint("21", "Q2"))
DynamicChart.Items.Add(New DataPoint("88", "Q3"))
DynamicChart.Items.Add(New DataPoint("34", "Q4"))
End If
End Sub
Via Data Binding - you can bind the Chart control to a data source control and the Chart will treat each record returned by the data source
control as a data point. To use this technique you must tell the Chart control what column in the data source control constitutes the data point value;
you can optionally specify what column constitutes the label. Use the DataValueField and DataLabelField properties to provide
this information.
ASP.NET server controls whose output depends on data and whose data can be specified through a data source control are referred to as data bound
controls. All such classes extend the BaseDataBoundControl
class, which defines the base functionality for such controls. Another class in the .NET Framework, DataBoundControl,
fleshes out the BaseDataBoundControl class, implementing some of the essential data binding logic and adding the DataMember property.
Consequently, the Chart control extends the DataBoundControl class.
(This article does not explore the art of creating data bound server
controls. For more information on this topic check out A Crash Course on ASP.NET Control
Development: Building Data-Bound Controls.)
The DataBoundControl class includes a method named PerformDataBinding that is executed in cases where the control is bound to
a data source control and this data is needed. The PerformDataBinding method is passed an object that implements IEnumerable, which
is the data returned by the data source control's Select() method. Custom server controls that extend DataBoundControl
typically override this method to provide the logic for rendering the underlying data. The Chart control overrides this method and uses it to populate
its Items collection, as the following code snippet illustrates:
protected override void PerformDataBinding(System.Collections.IEnumerable data)
{
... Some code removed for bevity ...
foreach (object point in data)
{
DataPoint item = new DataPoint();
When the Chart control is rendered it renders as an <img> element with its src attribute assigned the appropriate URL
to render the chart using the Google Chart API. The precise HTML element that is rendered by a Web control depends on the value of its
TagKey property. Because we need
the Chart control to render as an <img> element (as opposed to a <span> or
<input>) the TagKey property is overridden to return the appropriate element type:
Whenever a Web control is rendered its AddAttributesToRender
method is invoked, which is responsible for adding any attributes within the HTML element. The Chart control overrides this method so that it can
translate the data in the Items collection (and the various appearance-related property settings) into the appropriate URL for the
src attribute.
As you can see from the above snippet of code, the src attribute is set to the value returned by the CreateChartUrl method.
This method, shown below, constructs the complete Google Chart API URL and querystring based on the control's properties and the data in the Items
collection.
protected virtual string CreateChartUrl()
{
StringBuilder sb = new StringBuilder(500);
// Add base Url
sb.Append(UrlBase);
// Add chart type
sb.Append("cht=").Append(GetChartTypeCode(this.ChartType));
// Add the title, if present
if (!string.IsNullOrEmpty(this.ChartTitle))
sb.Append("&chtt=").Append(HttpUtility.UrlEncode(this.ChartTitle));
... Some Code Omitted for Brevity ...
// Specify data
sb.Append("&chd=t:").Append(this.Items.RenderRelativeCHDValues(2));
return sb.ToString();
}
The CreateChartUrl method starts by creating a new StringBuilder object and adds the value of the UrlBase property
(the portion of the Google Chart API URL without the querystring values, http://chart.apis.google.com/chart?). It then adds the
chart type parameter (cht), the chart dimensions (chs), and so on. The values for these parameters are pulled from the
values of the control's properties. A number of other querystring parameter assignment statements have been omitted from the above snippet for the sake of
brevity. The most important step is specifying the chart data (chd). The Items collection has a method named
RenderRelativeCHDValues that returns the values in the collection in the format required by the chd querystring parameter.
As discussed in last week's Creating Charts with the Google Chart API article
the values for the chd parameter, when specified using text formatting, should be a comma-delimited list of values between 0 and 100
where the largest data point has a value of 100 and all other data points are expressed as a percentage of the largest. This computation is handled within
the RenderRelativeCHDValues method.
The net result is that the Chart control renders an <img> element with an appropriate src attribute, just like we did
in last week's article. But instead of having to create that src attribute ourselves, the Chart control does that for us. All we have to
do is set a few properties and specify the data to plot.
Using the Chart Control in an ASP.NET Page
The download available at the end of this article includes the complete source code for the Chart control, as well as a demo ASP.NET website. To
use the skmControls2 controls in an ASP.NET website, copy the DLL to the website's Bin directory and then add the following
@Register directive to the tops of the .aspx pages where you want to use the controls:
You can now go to the Design view and see its properties, bind it to a data source control, and so on.
(You can also add the control to your Toolbox in Visual Studio by: right-clicking on the Toolbox; selecting Choose Items; going to the Browse tab;
and browing to the skmControls2.dll assembly. Once added to the Toolbox you can add the Chart control to a page by dragging it from
the Toolbox onto the page's Design surface or declarative markup portion.)
The demo for download at the end of this article includes three Chart control examples. Two of them (GoogleChartDemo.aspx and
GoogleChartDemo2.aspx) use AccessDataSource controls to display category sales data from the Northwind database. The following screen
shot shows is from GoogleChartDemo2.aspx. There are two TextBox controls in which the user can filter the dates. Upon entering dates and
clicking the "Refresh Data" button the page shows the results in a GridView control as well as in the Chart control. This functionality is possible
without having to write a single line of code!
Note that in the line chart the names of the categories overlap a bit. You could fix this by increasing the width of the chart or by formatting the
category names so that they only include the first few letters. GoogleChartDemo.aspx shows how to programmatically format the chart's data in this
fashion.
The third demo (GoogleChartDemo3.aspx) contains a chart whose data is constructed programmatically. In particular, this third demo enumerates
the files in the web application's root directory and sums up the total file size for each unique file extension. It then displays this data in a pie chart.
As you can see by the screen shot below, there are four unique file extensions - .aspx, .vb, .config, and
.png - with .aspx files comprising more disk space than all of the other file types combined.
Conclusion
The Google Chart API offers a free and easy way to generate charts - simply craft an appropriately formatted URL, put it in the src attribute
of an <img> element, and, voila, you have a chart on your web page. Unfortunately, there's a bit of work involved in constructing
the querystring. Rather than having to memorize the assorted querystring parameters or toil writing code to generate that query, it would be easier to
use a custom server control that did all that for us. The Chart control in the skmControls2 Library is such a control and, as we saw in this article,
is can be used to generate simple charts using the Google Chart API.