Building a Bar Chart in CS and VB: Opinion Poll

Recently we worked on an online opinion poll which is a pluggable module to our CMS. The poll is a survey of public opinion (e.g., do you like this product?) from a particular sample. Sampling is that part of statistical practice concerned with the selection of individual observations intended to yield some knowledge about a population of concern, especially for the purposes of statistical inference. Opinion polls are usually designed to represent the opinions of a population by conducting a series of questions and then extrapolating generalities in ratio or within confidence intervals.

One of the obstables that we encountered is producing the results of the poll in a bar chart. A typical Windows Live Search returns a number of charting controls such as Dundas Chart for .NET. we are very impressed with this product as we have previously used this product in one of my projects. Anyway, my ultimate objective is to build the bar chart from stratch. So we began drafting on a piece of paper a class diagram. Upfront in my mind, I need a class serving as a holder to store all the entries for x and y axis of the bar chart. We called this class as XYAxis.

CS Code

using System;

public class XYAxis {

private string x = null;
private int y = 0;

public XYAxis() {
}

public string X {
get {
return this.x;
}
set {
this.x = value;
}
}

public int Y {
get {
return this.y;
}
set {
this.y = value;
}
}

public override string ToString() {
return String.Format("XYAxis= X: {0}, Y: {1}", x, y);
}

}

VB Code

Public Class XYAxis

Private _X As String
Private _Y As Integer

Public Property X() As String
Get
Return _X
End Get
Set(ByVal value As String)
_X = value
End Set
End Property

Public Property Y() As Integer
Get
Return _Y
End Get
Set(ByVal value As Integer
_Y = value
End Set
End Property

Public Overrides Function ToString() As String
Return String.Format("XYAxis= X: {0}, Y: {1}", _X, _Y)
End Function

End Class

As you can see in the above code that the XYAxis class contains two properties one represents the X axis and the other one represents the Y axis. My next task is to publish the bar chart. So what we have in our minds are to build another class that does the actual drawing of the bar chart. The complete implementation of the class is as follows:

CS Code

using System;
using System.Drawing;
using System.Collections.Generic;
using System.Diagnostics;

public class BarChart{

private const int SCALE = 100;
private const int CANVAS_HEIGHT = 250;
private const int GRAPH_MARGIN = 80;
private const int BAR_GRAPH_WIDTH = 50;

public BarChart() {
}

public static Bitmap draw(List list) {
int margin = 0;
Bitmap bitmap = null;
Graphics graphics = null;
Point point;
Rectangle rectangle1;
Rectangle rectangle2;

try {
bitmap = new Bitmap(list.Count * SCALE, CANVAS_HEIGHT);
graphics = Graphics.FromImage(bitmap);
graphics.FillRectangle(Brushes.White, 0, 0, list.Count * SCALE, CANVAS_HEIGHT);
foreach (var xyAxis in list) {
point = new Point();
point.X = margin;
point.Y = bitmap.Height - 40 - xyAxis.Y;
rectangle1 = new Rectangle(point, new Size(BAR_GRAPH_WIDTH, xyAxis.Y));
point = new Point(); point.X = 0; point.Y = 210;
rectangle2 = new Rectangle(point, new Size(list.Count * SCALE, 1));
graphics.FillRectangle(Brushes.Gray, rectangle1);
graphics.FillRectangle(Brushes.Blue, rectangle2);
graphics.DrawString(xyAxis.Y.ToString(), new Font("Verdana", 10), Brushes.Blue, new PointF(rectangle1.X, rectangle1.Y - 20));
graphics.DrawString(xyAxis.X, new Font("Verdana", 8), Brushes.Blue, new PointF(rectangle1.X, 220)); margin += GRAPH_MARGIN;
}
} catch (Exception exception) {
Debug.Write(exception.Message);
}
return bitmap;
}
}

VB Code

Imports System.Drawing

Public Class BarChart

Private Const SCALE As Integer = 100
Private Const CANVAS_HEIGHT As Integer = 250
Private Const GRAPH_MARGIN As Integer = 80
Private Const BAR_GRAPH_WIDTH As Integer = 50

Public Sub New()
End Sub

Public Shared Function Draw(ByVal _List As List(Of XYAxis)) As Bitmap
Dim _Bitmap As Bitmap = Nothing
Dim _Graphics As Graphics = Nothing
Dim _Margin As Integer = 0
Dim _Rectangle1 As Rectangle = Nothing
Dim _Rectangle2 As Rectangle = Nothing
Dim _Point As Point = Nothing

Try
_Bitmap = New Bitmap(_List.Count * SCALE, CANVAS_HEIGHT)
_Graphics = Graphics.FromImage(_Bitmap)
_Graphics.FillRectangle(Brushes.White, 0, 0, _List.Count * SCALE, CANVAS_HEIGHT)
For Each _XYAxis As XYAxis In _List
_Point = New Point()
_Point.X = _Margin
_Point.Y = _Bitmap.Height - 40 - _XYAxis.Y
_Rectangle1 = New Rectangle(_Point, New Size(BAR_GRAPH_WIDTH, _XYAxis.Y))
_Point = New Point()
_Point.X = 0
_Point.Y = 210
_Rectangle2 = New Rectangle(_Point, New Size(_List.Count * SCALE, 1))
_Graphics.FillRectangle(Brushes.Gray, _Rectangle1)
_Graphics.FillRectangle(Brushes.Blue, _Rectangle2)
_Graphics.DrawString(_XYAxis.Y.ToString(), New Font("Verdana", 10), Brushes.Blue, New PointF(_Rectangle1.X, _Rectangle1.Y - 20))
_Graphics.DrawString(_XYAxis.X, New Font("Verdana", 8), Brushes.Blue, New PointF(_Rectangle1.X, 220))
_Margin = _Margin + GRAPH_MARGIN
Next _XYAxis
Catch _Exception As Exception
Debug.Write(_Exception.Message)
End Try
Return _Bitmap
End Function

End Class

Now we are ready to publish the bar chart. In my [Page].aspx.vb or [Page].aspx.cs Page_Load method, I instantiate a List of XYAxis and populate a few instance of XYAxis (along with some sample entries) into the List.

Sample CS Code Snippet

XYAxis xyAxis = null;
xyAxis = new XYAxis();
xyAxis.X = "Product 1";
xyAxis.Y = 20;
list.Add(xyAxis);
xyAxis = new XYAxis();
xyAxis.X = "Product 2";
xyAxis.Y = 2;
list.Add(xyAxis);
xyAxis = new XYAxis();
xyAxis.X = "Product 3";
xyAxis.Y = 80;
list.Add(xyAxis);
xyAxis = new XYAxis();
xyAxis.X = "Product 4";
xyAxis.Y = 48;
list.Add(xyAxis);
xyAxis = new XYAxis();
xyAxis.X = "Product 5";
xyAxis.Y = 21;
list.Add(xyAxis);
xyAxis = new XYAxis();
xyAxis.X = "Product 6";
xyAxis.Y = 10;
list.Add(xyAxis);

Sample VB Code Snippet

Dim _XYAxis As XYAxis
_XYAxis = New XYAxis
_XYAxis.X = "Product 1"
_XYAxis.Y = 20
_List.Add(_XYAxis)
_XYAxis = New XYAxis
_XYAxis.X = "Product 2"
_XYAxis.Y = 2
_List.Add(_XYAxis)
_XYAxis = New XYAxis
_XYAxis.X = "Product 3"
_XYAxis.Y = 80
_List.Add(_XYAxis)
_XYAxis = New XYAxis
_XYAxis.X = "Product 4"
_XYAxis.Y = 48
_List.Add(_XYAxis)
_XYAxis = New XYAxis
_XYAxis.X = "Product 5"
_XYAxis.Y = 21
_List.Add(_XYAxis)
_XYAxis = New XYAxis
_XYAxis.X = "Product 6"
_XYAxis.Y = 10
_List.Add(_XYAxis)

Now what we need is a LinkButton to actually trigger the drawing of the bar chart. So we drag a LinkButton from the Toolbox to my [Page].aspx and specify the Text property as Draw Bar Chart. Then we implement the following in my LinkButton1_Click method (assuming that the LinkButton is declared as LinkButton1):

Sample CS Code Snippet

BarChart.draw(list).Save(Response.OutputStream, ImageFormat.Gif);

Sample VB Code Snippet

BarChart.Draw(_List).Save(Response.OutputStream, ImageFormat.Gif)

Then we hit Ctrl+F5 to run my Web application. After the page is shown on the browser, we are ready to click Draw Bar Chart to publish the bar chart. The following are some sample screenshots.







Our past activities

K365Labs on Facebook