Creating the bar chart

The bar chart is yet another example of a GDI+ chart. This chart displays the amount of sales for the last three months, and is a good demonstration of the GDI+ FillRectangle method.

Add a new usercontrol named BarChart to your project, and set its background color to pure white. You will again pass in XML data via the Datasource property.

private XmlElement _dataSource = null;

public XmlElement Datasource {

return _dataSource;

_dataSource = value;

if (_dataSource != null) {AnalyzeData();} this.Refresh();

private void AnalyzeData() {

int _counter; XmlElement _xmlDay; int _value;

//Extracts the values from the XML element into an array _HighestValue = 0;

for (_counter = 0; _counter <= _dataSource.ChildNodes.Count

_xmlDay = (System.Xml.XmlElement)

(_dataSource.ChildNodes.Item(_counter)); _value = int.Parse(_xmlDay.GetAttribute("Value")); _DataValues[_counter] = _value;

_HighestValue = Math.Max(_value, _HighestValue);

You also need to declare the following variables that will be used throughout the bar chart.

//The highest value to be displayed in the chart private int _HighestValue;

//An array containing values for each month in the monthscale private long[] _DataValues = new long[4];

//Horizontal margin of the chart private int _marginX = 20;

//Vertical margin of the chart private int _marginY = 20;

//Vertical spacing between each gridline private int _gridlineSpacing = 9;

//Vertical spacing between each label on the Y Axis private int _YAxisLabelSpacing = 18;

//Number of horizontal pixels to render for each day in the dayscale private int _XPixelsPerDay;

//Bottom coordinate of the chart area private int _chartBottom;

//Top coordinate of the chart area private int _chartTop;

//Left coordinate of the chart area private int _chartLeft;

//Right coordinate of the chart area private int _chartRight;

//Height of the chart area private int _chartHeight;

//Width of the chart area private int _chartWidth;

//The value that each pixel in the chart area represents vertically private double _ValuePerChartPixel;

//The base of the number private int _BaseOfValue = 1000000;

//Pens and brushes used throughout the bar chart private Pen _blackPen=new Pen(Color.Black);

private SolidBrush _blackBrush= new SolidBrush(Color.Black); private SolidBrush _redBrush= new SolidBrush(Color.Red); private SolidBrush _blueBrush= new SolidBrush(Color.Blue); private SolidBrush _greenBrush= new SolidBrush(Color.Green);

//Fonts used throughout the bar chart private Font _stdFont = new Font("Tahoma", 8, FontStyle.Regular); private Font _smallFont = new Font("Tahoma", 6, FontStyle.Regular); private Font _boldFont = new Font("Tahoma", 8, FontStyle.Bold);

You will need to override the 0nPaint() event for this usercontrol.

public void BarChart_Paint(object sender, System.Windows.Forms.PaintEventArgs e)

LoadBarChart(e.Graphics);

public void BarChart_Resize(object sender, System.EventArgs e) {

this.Refresh();

The LoadBarChart() method does the bulk of the drawing for the bar chart usercontrol.

private void LoadBarChart(Graphics Graphics) {

int _counter;

//Calculate chart dimensions _chartTop = _marginY;

_chartBottom = this.Height - _marginY;

_chartLeft = _marginX;

_chartRight = this.Width - _marginX;

_chartHeight = _chartBottom - _chartTop;

_chartWidth = _chartRight - _chartLeft;

_ValuePerChartPixel = (_HighestValue)/ _chartHeight;

//If no datasource was loaded, we display a message to //indicate that data is loading if (_dataSource == null) {

Graphics.DrawString("Loading data...", _stdFont, _blackBrush, 15, 15);

return;

//Draw Chart title

Graphics.DrawString("Monthly sales ($M)", _boldFont, _blackBrush, 2, 2);

Graphics.DrawLine(_blackPen, _chartLeft, _chartTop,

_chartLeft, _chartBottom);

Graphics.DrawLine(_blackPen, _chartLeft, _chartBottom, _chartRight, _chartBottom);

//Draw Y axis labels _counter = 0; double _LabelValue;

//Draw the label hair

Graphics.DrawLine(_blackPen, _chartLeft - 3,

_chartBottom - _counter, _chartLeft - 1, _chartBottom

//Get the value at the label, and convert them to the correct base _LabelValue = _ValuePerChartPixel * _counter; _LabelValue = _LabelValue / _BaseOfValue;

//Draw the label

Graphics.DrawString(Strings.Format(_LabelValue, "#0.0"), _smallFont, _blackBrush, 0, VAlignMiddle(_chartBottom

_counter = _counter + _YAxisLabelSpacing;

//Draw X axis labels

_XPixelsPerDay = (int) ((_chartWidth)/ 3); int _x = _chartLeft; int _YPos1; string _monthName;

SolidBrush[] _bars = new SolidBrush[4];

//Initialize different colors for each bar _bars[0] = _blueBrush; _bars[1] = _greenBrush; _bars[2] = _redBrush;

//Draw the X-Axis hairs

Graphics.DrawLine(_blackPen, _x, _chartBottom + 1, _x,

_chartBottom + 6); Graphics.DrawLine(_blackPen, _x + _XPixelsPerDay,

_chartBottom + 1, _x + _XPixelsPerDay, _chartBottom + 6);

//Draw X-Axis labels

_monthName = DateAndTime.MonthName(DateTime.Now.Month +

_counter - 2, true); Graphics.DrawString(_monthName, _smallFont, _blackBrush,

//Draw the data bars

_YPos1 = _chartBottom - ConvertValueToPixels((int) (_DataValues[_counter]));

Graphics.FillRectangle(_bars[_counter], _x, _YPos1, _XPixelsPerDay, ConvertValueToPixels((int) (_DataValues[_counter])));

//This method converts a sales amount into a Y coordinate on //the line chart private int ConvertValueToYCoordinate(int Value) {

return _chartBottom - (int) ((Value)/ _ValuePerChartPixel);

//This method middle-aligns the Y-axis labels vertically private int VAlignMiddle(int Y) {

As with the other charts, you need to modify the LoadDashboard() method to load the bar chart usercontrol.

private BarChart _barChartControl;

private void LoadDashboard() {

_barChartControl = new BarChart(); _barChartControl.Dock = DockStyle.Fill; _barChartControl.Visible = true; pnlBarChart.Controls.Add(_barChartControl);

As a last step, you will need to call the Begininvoke() method to pass the <LastThreeMonthSales> XML node into the bar chart usercontrol.

private delegate void

PopulateBarChartControlDelegate(XmlElement Data);

private void BeginGetChartDataCallback(IAsyncResult Result) {

//Look for the node of the last three month of sales and //load it into the bar chart control _xmlLastThreeMonthSales = (System.Xml.XmlElement)

(_xmlRoot.GetElementsByTagName ("LastThreeMonthSales")[0]); PopulateBarChartControlDelegate _barchartDelegate = new

PopulateBarChartControlDelegate (PopulateBarChartControl); this.BeginInvoke(_barchartDelegate, _xmlLastThreeMonthSales);

private void PopulateBarChartControl(XmlElement Data) {

_barChartControl.Datasource = Data;

If you try running your application again, you will be able to see the bar chart rendered in the following fashion:

Now, try something different—try resizing the chart areas by dragging the splitters; all three charts will resize automatically (shown as follows):

You can additionally provide a manual refresh function to your end users so that clicking on the Refresh menu item will initiate a reconnection to the remote web service for the latest data.

public void mnuRefresh_Click(System.Object sender,System.EventArgs e) {

RefreshAllCharts();

Was this article helpful?

0 0

Post a comment