Sample Code: DataGridView progress bar column

I have a column that has integer data in it, I want to display it as a progress bar in the column so the user can quickly identify lagging processes.

 

I just started with 2005 and it looks great but does anyone know a quick way to do this

I would also like to change the color of the progress bar based on the cells value.

I found in the data sources toolbox where I can change the column to progress bar but that does not pass through to the grid.

 

Thanks for ANY help with this



Answer this question

Sample Code: DataGridView progress bar column

  • Cyberjunkie

    Here is an unsupported progress bar cell/column sample in VB and C#:

    VB:



    '---------------------------------------------------------------------
    ' THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
    ' KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
    ' IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
    ' PARTICULAR PURPOSE.
    '---------------------------------------------------------------------

    Imports System.Drawing
    Imports System.ComponentModel

    Public Class DataGridViewProgressColumn
        Inherits DataGridViewImageColumn

        Public Sub New()
            Me.CellTemplate = New DataGridViewProgressCell
        End Sub

    End Class
    Public Class DataGridViewProgressCell
        Inherits DataGridViewImageCell
       
        Sub New()
            ValueType = Type.GetType("Integer")
        End Sub

        ' Method required to make the Progress Cell consistent with the default Image Cell.
        ' The default Image Cell assumes an Image as a value, although the value of the Progress Cell is an Integer.
        Protected Overrides Function GetFormattedValue( _
            ByVal value As Object, _
            ByVal rowIndex As Integer, _
            ByRef cellStyle As DataGridViewCellStyle, _
            ByVal valueTypeConverter As TypeConverter, _
            ByVal formattedValueTypeConverter As TypeConverter, _
            ByVal context As DataGridViewDataErrorContexts _
            ) As Object

            Static emptyImage As Bitmap = New Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
            GetFormattedValue = emptyImage
        End Function


        Protected Overrides Sub Paint(ByVal g As System.Drawing.Graphics, ByVal clipBounds As System.Drawing.Rectangle, ByVal cellBounds As System.Drawing.Rectangle, ByVal rowIndex As Integer, ByVal cellState As System.Windows.Forms.DataGridViewElementStates, ByVal value As Object, ByVal formattedValue As Object, ByVal errorText As String, ByVal cellStyle As System.Windows.Forms.DataGridViewCellStyle, ByVal advancedBorderStyle As System.Windows.Forms.DataGridViewAdvancedBorderStyle, ByVal paintParts As System.Windows.Forms.DataGridViewPaintParts)
            Dim progressVal As Integer = CType(value, Integer)
            Dim percentage As Single = CType((progressVal / 100), Single)
            Dim backBrush As Brush = New SolidBrush(cellStyle.BackColor)
            Dim foreBrush As Brush = New SolidBrush(cellStyle.ForeColor)

            ' Call the base class method to paint the default cell appearance.
            MyBase.Paint(g, clipBounds, cellBounds, rowIndex, cellState, _
                value, FormattedValue, ErrorText, cellStyle, _
                advancedBorderStyle, paintParts)

            If percentage > 0.0 Then
                ' Draw the progress bar and the text
                g.FillRectangle(New SolidBrush(Color.FromArgb(163, 189, 242)), cellBounds.X + 2, cellBounds.Y + 2, Convert.ToInt32((percentage * cellBounds.Width - 4)), cellBounds.Height - 4)
                g.DrawString(progressVal.ToString() & "%", cellStyle.Font, foreBrush, cellBounds.X + 6, cellBounds.Y + 2)
            Else
                'draw the text

                If Not Me.DataGridView.CurrentCell Is Nothing AndAlso Me.DataGridView.CurrentCell.RowIndex = rowIndex Then
                    g.DrawString(progressVal.ToString() & "%", cellStyle.Font, New SolidBrush(cellStyle.SelectionForeColor), cellBounds.X + 6, cellBounds.Y + 2)
                Else
                    g.DrawString(progressVal.ToString() & "%", cellStyle.Font, foreBrush, cellBounds.X + 6, cellBounds.Y + 2)
                End If
            End If
        End Sub

    End Class
     

    Here is the C# version:


    //---------------------------------------------------------------------
    //THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
    //KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
    //IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
    //PARTICULAR PURPOSE.
    //---------------------------------------------------------------------

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Windows.Forms;
    using System.Drawing;
    using System.ComponentModel;

    namespace Sample
    {
        public class DataGridViewProgressColumn : DataGridViewImageColumn
        {
            public DataGridViewProgressColumn()
            {
                CellTemplate = new DataGridViewProgressCell();
            }
        }
    }

    namespace Sample
    {
        class DataGridViewProgressCell : DataGridViewImageCell 
        {
            // Used to make custom cell consistent with a DataGridViewImageCell
            static Image emptyImage;
            static DataGridViewProgressCell()
            {
                emptyImage = new Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            }

            public DataGridViewProgressCell()
            {
                this.ValueType = typeof(int);
            }

            // Method required to make the Progress Cell consistent with the default Image Cell.
            // The default Image Cell assumes an Image as a value, although the value of the Progress Cell is an int.
            protected override object GetFormattedValue(object value,
                                int rowIndex, ref DataGridViewCellStyle cellStyle,
                                TypeConverter valueTypeConverter,
                                TypeConverter formattedValueTypeConverter,
                                DataGridViewDataErrorContexts context)
            {
                return emptyImage;
            }

           
            protected override void Paint(System.Drawing.Graphics g, System.Drawing.Rectangle clipBounds, System.Drawing.Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
            {
                int progressVal = (int)value;
                float percentage = ((float)progressVal / 100.0f); // Need to convert to float before division; otherwise C# returns int which is 0 for anything but 100%.
                Brush backColorBrush = new SolidBrush(cellStyle.BackColor);
                Brush foreColorBrush = new SolidBrush(cellStyle.ForeColor);

                // Draws the cell grid
                base.Paint(g, clipBounds, cellBounds,
                 rowIndex, cellState, value, formattedValue, errorText,
                 cellStyle, advancedBorderStyle, (paintParts & ~DataGridViewPaintParts.ContentForeground));

                if (percentage > 0.0)
                {
                    // Draw the progress bar and the text
                    g.FillRectangle(new SolidBrush(Color.FromArgb(163, 189, 242)), cellBounds.X + 2, cellBounds.Y + 2, Convert.ToInt32((percentage * cellBounds.Width - 4)), cellBounds.Height - 4);
                    g.DrawString(progressVal.ToString() + "%", cellStyle.Font, foreColorBrush, cellBounds.X + 6, cellBounds.Y + 2);
                }
                else
                {
                    // draw the text
                    if (this.DataGridView.CurrentRow.Index == rowIndex)
                        g.DrawString(progressVal.ToString() + "%", cellStyle.Font, new SolidBrush(cellStyle.SelectionForeColor), cellBounds.X + 6, cellBounds.Y + 2);
                    else
                        g.DrawString(progressVal.ToString() + "%", cellStyle.Font, foreColorBrush, cellBounds.X + 6, cellBounds.Y + 2);
                }
            }
        }
    }

     

    -mark
    DataGridView Program Manager
    Microsoft
    This post is provided "as-is"


  • BAZOOKAMEGATRON

    Nope - just add the classes to your application. Compile once and then you can goto the Edit columns dialog and add a progress bar column. If you are databound, then you can just change the column type of an integer column that has 0 through 100 values.< xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

     

    -mark

    DataGridView Program Manager

    Microsoft

    This post is provided “as-is”

     


  • Adam.Kahtava

    Check out the FAQ. The DataGridView does not support embedding controls in the cells. The grid only draws the cells to look like controls. Only when a cell is in edit mode does it actually host a control.< xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

     

    -mark

    DataGridView Program Manager

    Microsoft

    This post is provided “as-is”

     

     


  • Kristian J&amp;#246;rgensen

    Thanks! I really appreciate it. The code I posted above compiles and is pretty much a direct conversion of the C# code, but I get that error, so I must have done something wrong or am missing something required in the C++ version. Feel free to give them a head start by posting my code if you like. Thanks again!

  • Muhammad Adnan

    OK, I made the class and added it and all worked well.

    Here is my question, why can't we just embed the progressbar control like we can the button or checkbox

    Thanks

     


  • 04-digit0l

    Please tell me how to do that check and whta value should I change for solving the design time problem.

  • Nicolas2608

    Thanks.... THAT IS SWEET!

    Here is my dilemma, to make this happen in all grids in my app I would I have to create a descendant DatGridView and put the code in it, correct

    If this is not correct please tell me how else I could accomplish this.

     


  • ssfftt

    Not sure I understand -- you just add a progress bar column and set the DataPropertyName when your DataGridView is showing content that you want. There is no support for auto changing a column's type, but you just remove and add a different DataGridView column type based upon what datasource you are showing. When the text of your label on the form identifies the datasource that should use the progress bar column you should just add it to the grid (and possibly remove any other columns). Does that make sense

    -mark
    DataGridView Program Manager
    Microsoft
    This post is provided "as-is"


  • R.Tutus

    Mark,

    This is a fantastic solution that I have spent the last couple of days searching for.  Very nice work.  Thank you for your contribution.

    I have a question about using this in my application.  For a single sourced datagrid, this works like a champ, very simple too.  My application, however uses a datagrid in which the user selects multiple sources of data for.  I would like to know how I can, based on the text of a label on the form, apply a datagridview progress bar to a column for only this source. 

    Can you explain how I might be able to do that    The other selected sources for data should not have a progressbar column.

    your help would be appreciated.

    Chris


  • corbin

    Hi Mark,

    I know that source code is provided "as-is", but do you have any input for me on the C++/CLR version I translated If you could just point me in the right direction I would be gratefull. Thanks!

  • ScottTarone

    I'll ask someone on the C# team if someone can convert the source. It might take a bit.

    -mark
    DataGridView Program Manager
    Microsoft
    This post is provided "as-is"


  • son of dad

    Hello,

    I got the same error because of the Paint method. At the design time, the value being pass in is null or whatever. What you can do is to make a quick check if the value is null or empty, then assign it = 1. It will solve the problem at the design time.

    have fun


  • BAZOOKAMEGATRON

    OK, thanks for the info.

     

    I have printed FAQ but have not had time to read the whole thing.

     

    Thanks agaion for your help.


  • Gep

    Hi.

    I found this code extremely useful, except I converted it to managed C++/CLR for a project I'm working on. It compiles and runs, but I get a runtime error and am unsure of what is causing it. Here is the error I get. I tried to display the screenshot inline but apparently it won't let me, so here's the link:

    DataGridView Default Error Dialog

    Here is the converted code. I used the C# version as a basis for the managed C++/CLR version. Keep in mind I don't really know C#, so I may have made a "rookie mistake" in translating it to C++/CLR. Can anyone please point me in the right direction to getting this to work Thanks.

  • Sample Code: DataGridView progress bar column