Add progress bar in gridview using datatable or da

2019-01-24 22:45发布

问题:

I need to add a progress bar in a DataGridView using DataTable or DataSet in a WinForms application similar to this:

Everywhere I've found has code like:

DataGridViewProgressColumn column = new DataGridViewProgressColumn();
column.HeaderText = "Status";
dataGridView1.Columns.Add(column);

and assign value with:

object[] row1 = new object[]  { "test1", "test2", 50 };

But I need this progress bar to be in a DataTable or DataSet.

回答1:

So this is example from msdn, with some correction. I use Datagridview, Timer, Button.

Now you need to use thread for your computing. I hope this will help.

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

    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 = 0;

            if (value != null)
                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);
            }
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        DataGridViewProgressColumn column = new DataGridViewProgressColumn();
        dataGridView1.Columns.Add(new DataGridViewProgressColumn());
        dataGridView1.Rows.Add("Row 1", 10);
        dataGridView1.Rows.Add("Row 2", 50);
        dataGridView1[1, 0].Value = 10;
        timer1.Start();
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        Random r=new Random();
        dataGridView1[1, 0].Value = r.Next(0, 100);
        dataGridView1[1, 1].Value = r.Next(0, 100);
    }


回答2:

There is no such thing as DataGridViewProgressColumn. To get an actual ProgressBar column will take some work - that is a ProgressBar that is embedded inside a cell...

The simplest way to achieve something like what you want is to have an animated .gif file within the relevant cell, so in this case you would use a DatGridViewImageColumn and select the required animate .gif as the image using a `PictureBox'.

To do smoothly will require multi-threading the process that you wish to show the progress of. The basic outline of how to do this would be

  1. Choose your animated .gif file from this amazing site.

  2. Import a Timer into your form and set the timer interval as '50'.

  3. Create a picture box on you form and set its size to "1, 1" (very small) and the image source to your animated .gif.

  4. Select this PictureBox as the DatGridViewImageColumn source image.

Then include the following code

private void yourTimerForGifAnimation_Tick(object sender, EventArgs e)
{
    this.dataGridView1.Rows[someRow].Cells["My Progress Bar Column"].Value = 
        this.pictureBoxGif.Image            
    this.dataGridView1.InvalidateCell(cellColumnIndex, cellRowIndex);
}

This will create your animated progress image. Now all you need to worry about is not doing work on the UI thread as this will cause the animation to free along with everything else!

I hope this helps.