ComponentOne BulletGraph for WinForms
Walkthrough / Using BulletGraph with DataGridView
In This Topic
    Using BulletGraph with DataGridView
    In This Topic

    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.

    bulletgraph-grid

    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:
    1. Create Data Source for DataGridView
    2. Configure DataGridView control
    3. Configure BulletGraph control
    4. Rendering BulletGraph In DataGridView
    Note: The BulletGraph control can also be rendered as an image in bound column of the DataGridView control using similar approach.

    Step 1: Create Data Source for DataGridView

    1. Create a new Windows Forms application.
    2. Drag and drop the MS DataGridView control from the Toolbox onto your form. From the Properties window, set its Dock property to Fill.
    3. To populate the DataGridView with data, create a data table containing relevant data.

    The code below defines a method named ‘CreateDataTable’ to create a data table that contains the country-wise sales information of a company.

    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
    
    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.

    Step 2: Configure DataGridView control

    1. To bind the grid with data, assign the data table created in the previous section to the DataGridView’s DataSource property.
    2. To display BulletGraph in DataGridView cells, add an additional unbound DataGridViewImageColumn to the DataGridView control.
    3. Optionally, customize the DataGridView’s appearance using appropriate properties of the DataGridView control.
    4. To render the BulletGraph control as an image in the added unbound column ‘SalesV/STarget’ of the DataGridView, subscribe to the CellPainting event of the DataGridView class.

    The code below creates a method named ‘SetUpGrid’, to configure the above mentioned settings of the DataGridView control.

    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
    
    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;
    }
    

    Step 3: Configure BulletGraph control

    1. 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:

      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
      
      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;
      }
      
      Note:The _bulletGraph is declared as a private global variable of type C1BulletGraph.

    Step 4: Rendering BulletGraph In DataGridView

    1. To render the BulletGraph control as an image in the ‘SalesV/STarget’ column of the DataGridView, use the DataGridView’s CellPainting event. In the CellPainting event handler, specify the values for the comparative measure, featured measure and qualitative ranges of the BulletGraph that needs to be drawn. We are setting these values in this event because for each bullet graph that is drawn in a specific row of the unbound column, these values will be different.
    2. Once the BulletGraph is fully configured, retrieve an image of the BulletGraph control with the help of the GetImage method of C1BulletGraph class.
    3. Draw the retrieved image in the DataGridView’s cell using the DrawImage method of Graphics class as shown:
      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
      
      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;
          }
      }
      
    4. Call the CreateDataTable, SetUpGrid and ConfigureBulletGraph methods in the Form1_Load event handler.
      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
      
      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();
      }
      
    5. Run the application. Observe how the bullet graphs are getting displayed in the ’SalesV/STarget’ column of the DataGridView control.