[]
Consider a scenario where you have data in a tabular format and you want to visualize the same using a visual control. This walkthrough explains how this scenario can be implemented using MS DataGridView as the control for tabular representation of data and BulletGraph as the control for visual representation of the same data.

The BulletGraph control can be rendered as an image in the DataGridView cells. To learn how this can be done, follow the steps given below:
type=note
Note: The BulletGraph control can also be rendered as an image in bound column of the DataGridView control using similar approach.
The code below defines a method named ‘CreateDataTable’ to create a data table that contains the country-wise sales information of a company.
vbnet
Private Sub CreateDataTable()
_dt = New DataTable()
_dt.Columns.Add("Country", GetType(String))
_dt.Columns.Add("Sales", GetType(Double))
_dt.Columns.Add("Target", GetType(Double))
_dt.Columns.Add("Bad", GetType(Double))
_dt.Columns.Add("Good", GetType(Double))
Dim countries As String() = {"US", "Germany", "Japan", "India", "China", "UK", "Denmark", "Indonesia"}
Dim random As Random = New Random()
For i As Integer = 0 To countries.Length - 1
Dim totalSales As Integer = random.[Next](0, 500)
Dim target As Integer = random.[Next](351, 499)
Dim bad As Integer = random.[Next](50, 200)
Dim good As Integer = random.[Next](201, 350)
_dt.Rows.Add(New Object() {countries(i), totalSales, target, bad, good})
Next
End Sub
csharp
private void CreateDataTable()
{
_dt = new DataTable();
_dt.Columns.Add("Country", typeof(String));
_dt.Columns.Add("Sales", typeof(Double));
_dt.Columns.Add("Target", typeof(Double));
_dt.Columns.Add("Bad", typeof(Double));
_dt.Columns.Add("Good", typeof(Double));
string[] countries = { "US", "Germany", "Japan", "India", "China", "UK", "Denmark", "Indonesia" };
Random random = new Random();
for (int i = 0; i < countries.Length; i++)
{
int totalSales = random.Next(0, 500);
int target = random.Next(351, 499);
int bad = random.Next(50, 200);
int good = random.Next(201, 350);
_dt.Rows.Add(new object[] { countries[i], totalSales, target, bad, good });
}
}
Note that _dt is declared as a private global variable of type DataTable.
The code below creates a method named ‘SetUpGrid’, to configure the above mentioned settings of the DataGridView control.
vbnet
Private Sub SetUpGrid()
DataGridView1.DataSource = _dt
'Add an unbound DataGridViewImageColumn to the DataGridView. This column will be used to show the BulletGraph control as an image
Dim dataGridViewImageColumn As DataGridViewImageColumn = New DataGridViewImageColumn()
dataGridViewImageColumn.Name = "SalesV/STarget"
DataGridView1.Columns.Add(dataGridViewImageColumn)
'Set additional properties of the DataGridView (optional)
DataGridView1.ColumnHeadersDefaultCellStyle.Font = New Font(FontFamily.GenericSansSerif, 8.5F, FontStyle.Bold)
DataGridView1.Font = New Font(FontFamily.GenericSansSerif, 9.0F, FontStyle.Regular)
DataGridView1.Columns(DataGridView1.Columns.Count - 1).AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
For i As Integer = 0 To DataGridView1.Rows.Count - 1
DataGridView1.Rows(i).Height = 40
Next
DataGridView1.RowHeadersVisible = False
DataGridView1.AllowUserToAddRows = False
DataGridView1.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
DataGridView1.DefaultCellStyle.Format = "$ #,##0"
DataGridView1.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
DataGridView1.Columns("Sales").HeaderText = "Sales" & vbLf & "(millions)"
DataGridView1.Columns("Target").HeaderText = "Target" & vbLf & "(millions)"
DataGridView1.Columns("Bad").HeaderText = "Bad" & vbLf & "(millions)"
DataGridView1.Columns("Good").HeaderText = "Good" & vbLf & "(millions)"
'Subscribe to the DataGridView's CellPainting event
AddHandler DataGridView1.CellPainting, AddressOf DataGridView1_CellPainting
End Sub
csharp
private void SetUpGrid()
{
dataGridView1.DataSource = _dt;
//Add an unbound DataGridViewImageColumn to the DataGridView. This column will be used to show the BulletGraph control as an image
DataGridViewImageColumn dataGridViewImageColumn = new DataGridViewImageColumn();
dataGridViewImageColumn.Name = "SalesV/STarget";
dataGridView1.Columns.Add(dataGridViewImageColumn);
//Set additional properties of the DataGridView (optional)
dataGridView1.ColumnHeadersDefaultCellStyle.Font= new Font(FontFamily.GenericSansSerif, 8.5f, FontStyle.Bold);
dataGridView1.Font = new Font(FontFamily.GenericSansSerif, 9f, FontStyle.Regular);
dataGridView1.Columns[dataGridView1.Columns.Count - 1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
dataGridView1.Rows[i].Height = 40;
}
dataGridView1.RowHeadersVisible = false;
dataGridView1.AllowUserToAddRows = false;
dataGridView1.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
dataGridView1.DefaultCellStyle.Format = "$ #,##0";
dataGridView1.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
dataGridView1.Columns["Sales"].HeaderText = "Sales\n(millions)";
dataGridView1.Columns["Target"].HeaderText = "Target\n(millions)";
dataGridView1.Columns["Bad"].HeaderText = "Bad\n(millions)";
dataGridView1.Columns["Good"].HeaderText = "Good\n(millions)";
//Subscribe to the DataGridView's CellPainting event
dataGridView1.CellPainting += DataGridView1_CellPainting;
}
Now create a global instance of the BulletGraph control and configure the general settings of the control. These settings will be applied to all the bullet graphs, which will be rendered in the DataGridView cells.
Note that although we need to display the BulletGraph in each row of the unbound column, we require only one instance of the BulletGraph control. This is because as we have already rendered the BulletGraph control’s image in the appropriate row, the same BulletGraph instance can be reconfigured to obtain the image for other bullet graphs.
The code given below defines a method named ‘ConfigureBulletGraph’ to instantiate the BulletGraph control and specify its general properties:
vbnet
Private Sub ConfigureBulletGraph()
'Configure the BulletGraph control
_bulletGraph = New C1BulletGraph()
_bulletGraph.Minimum = 0 'Sets the starting value of the quantitative scale
_bulletGraph.Maximum = 500 'Sets the ending value of the quantitative scale
_bulletGraph.GraphScale.ShowLabels = False 'Hides the scale labels
_bulletGraph.GraphScale.ShowMarks = False 'Hides the scale tick marks
'Styling the BulletGraph control
_bulletGraph.BackColor = Color.White
_bulletGraph.Styles.Ranges.Value.Color = Color.SteelBlue
_bulletGraph.Styles.Ranges.Bar.Border.Color = Color.Gray
_bulletGraph.Styles.Ranges.Bar.Border.LineStyle = C1GaugeBorderStyle.Solid
End Sub
csharp
private void ConfigureBulletGraph()
{
//Configure the BulletGraph control
_bulletGraph = new C1BulletGraph();
_bulletGraph.Minimum = 0; //Sets the starting value of the quantitative scale
_bulletGraph.Maximum = 500; //Sets the ending value of the quantitative scale
_bulletGraph.GraphScale.ShowLabels = false; //Hides the scale labels
_bulletGraph.GraphScale.ShowMarks = false; //Hides the scale tick marks
//Styling the BulletGraph control
_bulletGraph.BackColor = Color.White;
_bulletGraph.Styles.Ranges.Value.Color = Color.SteelBlue;
_bulletGraph.Styles.Ranges.Bar.Border.Color = Color.Gray;
_bulletGraph.Styles.Ranges.Bar.Border.LineStyle = C1GaugeBorderStyle.Solid;
}
type=note
Note:The _bulletGraph is declared as a private global variable of type C1BulletGraph.
Draw the retrieved image in the DataGridView’s cell using the DrawImage method of Graphics class as shown:
vbnet
Private Sub DataGridView1_CellPainting(ByVal sender As Object, ByVal e As DataGridViewCellPaintingEventArgs)
If e.RowIndex >= 0 AndAlso DataGridView1.Columns(e.ColumnIndex).Name = "SalesV/STarget" Then
_bulletGraph.Bounds = e.CellBounds
_bulletGraph.Value = CDbl(_dt.Rows(e.RowIndex)("Sales")) 'Sets the value of the featured measure
_bulletGraph.Target = CDbl(_dt.Rows(e.RowIndex)("Target")) 'Sets the value of the comparative measure
_bulletGraph.Bad.To = CDbl(_dt.Rows(e.RowIndex)("Bad")) 'Sets the ending value of the good range
_bulletGraph.Good.To = CDbl(_dt.Rows(e.RowIndex)("Good")) 'Sets the ending value of the bad range
'Retrieve the BulletGraph image and draw the retrieved image in the DataGridView's cell
Dim bulletGraphImg As Image = _bulletGraph.GetImage()
e.Graphics.DrawImage(bulletGraphImg, e.CellBounds)
e.Paint(e.CellBounds, DataGridViewPaintParts.Border)
e.Handled = True
End If
End Sub
csharp
private void DataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.RowIndex >= 0 && dataGridView1.Columns[e.ColumnIndex].Name == "SalesV/STarget")
{
_bulletGraph.Bounds = e.CellBounds;
_bulletGraph.Value = (double)_dt.Rows[e.RowIndex]["Sales"]; //Sets the value of the featured measure
_bulletGraph.Target = (double)_dt.Rows[e.RowIndex]["Target"]; //Sets the value of the comparative measure
_bulletGraph.Bad.To = (double)_dt.Rows[e.RowIndex]["Bad"]; //Sets the ending value of the good range
_bulletGraph.Good.To = (double)_dt.Rows[e.RowIndex]["Good"]; //Sets the ending value of the bad range
//Retrieve the BulletGraph image and draw the retrieved image in the DataGridView's cell
Image bulletGraphImg = _bulletGraph.GetImage();
e.Graphics.DrawImage(bulletGraphImg, e.CellBounds);
e.Paint(e.CellBounds,DataGridViewPaintParts.Border);
e.Handled = true;
}
}
Call the CreateDataTable, SetUpGrid and ConfigureBulletGraph methods in the Form1_Load event handler.
vbnet
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'Creates DataTable which will be used as the DataSource for the DataGridView
CreateDataTable()
'Adds an unbound column to the DataGridView and sets the DataGridView properties
SetUpGrid()
'Sets the common properties of the BulletGraph control
ConfigureBulletGraph()
End Sub
csharp
private void Form1_Load(object sender, EventArgs e)
{
//Creates DataTable which will be used as the DataSource for the DataGridView
CreateDataTable();
//Adds an unbound column to the DataGridView and sets the DataGridView properties
SetUpGrid();
//Sets the common properties of the BulletGraph control
ConfigureBulletGraph();
}
Run the application. Observe how the bullet graphs are getting displayed in the ’SalesV/STarget’ column of the DataGridView control.