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 | | Stephen Hauck Wednesday, December 21, 2005 6:47 PM | 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"
| | Mark Rideout Wednesday, December 21, 2005 9:39 PM | 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"
| | Mark Rideout Wednesday, December 21, 2005 9:39 PM | 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.
| | Stephen Hauck Wednesday, December 21, 2005 9:57 PM | 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.
-mark
DataGridView Program Manager
Microsoft
This post is provided “as-is�/SPAN>
| | Mark Rideout Wednesday, December 21, 2005 10:10 PM | 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
| | Stephen Hauck Wednesday, December 21, 2005 10:50 PM | 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.
-mark
DataGridView Program Manager
Microsoft
This post is provided “as-is�/SPAN>
| | Mark Rideout Wednesday, December 21, 2005 10:54 PM | OK, thanks for the info.
I have printed FAQ but have not had time to read the whole thing.
Thanks agaion for your help. | | Stephen Hauck Thursday, December 22, 2005 12:10 PM | 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.
#pragma once
//--------------------------------------------------------------------- //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 namespace System; using namespace System::Collections::Generic; using namespace System::Text; using namespace System::Windows::Forms; using namespace System::Drawing; using namespace System::ComponentModel;
ref class DataGridViewProgressCell : public DataGridViewImageCell { public: // Used to make custom cell consistent with a DataGridViewImageCell static Image^ emptyImage; static DataGridViewProgressCell() { emptyImage = gcnew Bitmap(1, 1, System::Drawing::Imaging::PixelFormat::Format32bppArgb); } DataGridViewProgressCell() { this->ValueType = Int32::typeid; } // 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: virtual Object^ GetFormattedValue(Object^ value, int rowIndex, DataGridViewCellStyle^ cellStyle, TypeConverter^ valueTypeConverter, TypeConverter^ formattedValueTypeConverter, DataGridViewDataErrorContexts^ context) override { return emptyImage; } protected:
virtual 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) override { int progressVal = (int)value; float percentage = ((float)progressVal * 0.01f); Brush^ backColorBrush = gcnew SolidBrush(cellStyle->BackColor); Brush^ foreColorBrush = gcnew SolidBrush(cellStyle->ForeColor);
// Draws the cell grid
DataGridViewImageCell::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(gcnew SolidBrush(Color::FromArgb(163, 189,
242)), cellBounds.X + 2, cellBounds.Y + 2, Convert::ToInt32((percentage
* cellBounds.Width - 4)), cellBounds.Height - 4); g->DrawString(progressVal + "%", cellStyle->Font, foreColorBrush, cellBounds.X + 6, cellBounds.Y + 2); } else { // draw the text if (this->DataGridView->CurrentRow->Index == rowIndex) {
g->DrawString(progressVal + "%", cellStyle->Font, gcnew
SolidBrush(cellStyle->SelectionForeColor), cellBounds.X + 6,
cellBounds.Y + 2); } else { g->DrawString(progressVal + "%", cellStyle->Font, foreColorBrush, cellBounds.X + 6, cellBounds.Y + 2); } } } };
public ref class DataGridViewProgressColumn : public DataGridViewImageColumn { public: DataGridViewProgressColumn() { CellTemplate = gcnew DataGridViewProgressCell(); } };
| | aaronexodus Wednesday, February 01, 2006 11:09 PM | 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 | | CMBrown Friday, February 17, 2006 12:03 AM | 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"
| | Mark Rideout Friday, February 17, 2006 12:11 AM | 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!
| | aaronexodus Friday, February 17, 2006 3:29 PM | 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"
| | Mark Rideout Saturday, February 18, 2006 1:54 AM | 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!
| | aaronexodus Saturday, February 18, 2006 6:38 AM | 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
| | Phong Nguyen Tuesday, March 28, 2006 9:45 PM | Please tell me how to do that check and whta value should I change for solving the design time problem. | | ssandu Friday, May 19, 2006 5:31 AM | I've modified the Paint method from the original sample code to paint an actual ProgressBar. It looks pretty nice. Modify the value of the margin variable to get the look you want.
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));
const int margin = 4;
ProgressBar pb = new ProgressBar();
pb.Height = cellBounds.Bottom - cellBounds.Top - (margin * 2);
pb.Width = cellBounds.Right - cellBounds.Left - (margin * 2);
pb.Value = progressVal;
Bitmap bmp = new Bitmap(pb.Width, pb.Height);
pb.DrawToBitmap(bmp, pb.ClientRectangle);
g.DrawImage(bmp, new Point(cellBounds.X + margin, cellBounds.Y + margin));
} | | Joel Harris Friday, June 02, 2006 7:02 PM | How do you "change the column type of an integer column" in the databound case? I'm just setting the DataSource property of a datagridview and it's automatically figuring out what type of columns to use. How do I make it use my new column type in certain situations? Is there a method I can override on datagridview? | | jeffand Thursday, July 13, 2006 6:37 PM | Im having the same error, any workarounds or fixes ? Im using .net 2.0 | | Abdullah.Ahmed Wednesday, July 26, 2006 5:16 AM | Here's how you fix that error. In the Virtual void Paint method....Replace
int progressVal = (int)value;
with
int progressVal; if(value!=null) progressVal = (int)value; else progressVal = 1;
Hope that helps... | | Abdullah.Ahmed Wednesday, July 26, 2006 7:33 AM |
|
Here's how you fix that error. In the Virtual void Paint method....Replace
int progressVal = (int)value;
with
int progressVal; if(value!=null) progressVal = (int)value; else progressVal = 1;
Hope that helps... | | | Abdullah.Ahmed Wednesday, July 26, 2006 7:36 AM | Many thanks, Mark.
Some obvious, little changes are required to make it designer friendly but this code allowed me to quickly get what I just needed.
Tomasz | | Tom Jastrzebski Monday, September 25, 2006 5:27 AM | The prototytpe for GetFormatedValue is Object^ DataGridViewProgressCell::GetFormattedValue(Object^ value, int rowIndex, DataGridViewCellStyle ^%cellStyle, TypeConverter^ valueTypeConverter, TypeConverter^ formattedValueTypeConverter, DataGridViewDataErrorContexts context)
| | The Assar Wednesday, October 04, 2006 1:59 PM | Hi group.
Quick question...
Is there any reason something like this would not be appropriate?
There is no mucking around with owner drawn stuff, and you get all the benefits of the regular progressbar control. Or am i missing something?
Public Class DataGridViewProgressBarColumn
Inherits DataGridViewImageColumn
Public Sub New()
Me.CellTemplate = New DataGridViewProgressBarCell
End Sub
End Class
Public Class DataGridViewProgressBarCell
Inherits DataGridViewImageCell
Public Sub New()
Me.ValueType = GetType(Integer)
End Sub
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
Dim bm As New Bitmap(OwningColumn.Width, OwningRow.Height)
Using g As Graphics = Graphics.FromImage(bm)
Using pb As New ProgressBar pb.Height = bm.Height pb.Width = bm.Width pb.Value = CInt(value) pb.DrawToBitmap(bm, New Rectangle(0, 0, bm.Width, bm.Height)) End Using
End Using
Return bm
End Function
End Class
| | blake1 Thursday, December 07, 2006 2:47 AM | Thanks alott! I've implemented this in C++ and it works just fine. But then came Vista! Seems like the Paint-method is not called when run in Vista.
Do anyone have a solution to this?
// Assar
Edit: Found out that Paint-method is called. However when calling DrawToBitmap it won't draw the the blocks representing the value.
Do anyone have a solution to this behaviour? | | The Assar Thursday, December 21, 2006 2:02 PM | Liked your solution! Won't work in Vista though, and neither did the previous solution. ProgressBar in Vista is smoth on startup and will not show green bar att all with this solution.
To solve the problem I've put the instance of progressbar in class. And: I want the actual value to display too. Use it and obuse it at your own will. Here is my (C++) solution, although not perfect.
DataGridViewProgressBar.h#pragma once
using namespace System; using namespace System::Collections::Generic; using namespace System::Text; using namespace System::Windows::Forms; using namespace System::Drawing; using namespace System::ComponentModel;
namespace Components { public ref class DataGridViewProgressCell : DataGridViewImageCell { private: ProgressBar^ mProgressBar;
public: DataGridViewProgressCell();
protected: virtual Object^ DataGridViewProgressCell::GetFormattedValue(Object^ value, int rowIndex, DataGridViewCellStyle ^%cellStyle, TypeConverter^ valueTypeConverter, TypeConverter^ formattedValueTypeConverter, DataGridViewDataErrorContexts context) override;
};
public ref class DataGridViewProgressColumn : DataGridViewImageColumn { public: DataGridViewProgressColumn(); }; }
DataGridViewProgressBar.cpp#include "StdAfx.h" #include "DataGridViewProgressBar.h"
using namespace System; using namespace System::Collections::Generic; using namespace System::Text; using namespace System::Windows::Forms; using namespace System::Drawing; using namespace System::ComponentModel;
using namespace Components;
DataGridViewProgressCell::DataGridViewProgressCell() { this->ValueType = int::typeid; this->mProgressBar = gcnew ProgressBar(); }
Object^ DataGridViewProgressCell::GetFormattedValue(Object^ value, int rowIndex, DataGridViewCellStyle ^%cellStyle, TypeConverter^ valueTypeConverter, TypeConverter^ formattedValueTypeConverter, DataGridViewDataErrorContexts context) { Bitmap^ bmp = gcnew Bitmap(OwningColumn->Width -1, OwningRow->Height -1); Bitmap^ bmptxt = gcnew Bitmap(OwningColumn->Width -1, OwningRow->Height -1); Label^ lbl = gcnew Label();
mProgressBar->Height = bmp->Height -4; mProgressBar->Width = bmp->Width -4; mProgressBar->BackColor = cellStyle->BackColor; mProgressBar->Style = ProgressBarStyle::Blocks; mProgressBar->Value = (int) value; mProgressBar->Update(); mProgressBar->DrawToBitmap(bmp, System::Drawing::Rectangle(2, 2, bmp->Width -4, bmp->Height -4));
lbl->AutoSize = false; lbl->TextAlign = ContentAlignment::MiddleCenter; lbl->Height = bmptxt->Height -4; lbl->Width = bmptxt->Width -4; lbl->Image = bmp; lbl->BackColor = cellStyle->BackColor; lbl->Text = String::Format( "{0}%", (int) value); lbl->DrawToBitmap(bmptxt, System::Drawing::Rectangle(2, 2, bmp->Width -4, bmp->Height -4));
return bmptxt; }
DataGridViewProgressColumn::DataGridViewProgressColumn() { CellTemplate = gcnew DataGridViewProgressCell(); }
| | The Assar Friday, December 22, 2006 12:36 PM | Hi Mark, Thanks for this posting the code. I would like to ask a few questions for update purposes: - Does the aforementioned code exist in any other location such a codeplex?
- Are there any updates since the initial post to be aware of?
- Does the next version of DataGridView support newer controls in the columns that .Net 2 version currently does not?
advTHANKSance | | OmegaMan Thursday, December 28, 2006 6:24 PM | Hi, I used the code of custom DataGridViewProgressColumn. Its good in runtime but unfortunately it is giving exception in Design mode. i.e whenever I am going to open the form containing the DataGridView, there is a messagebox of Exception : Object Reference not set shown. But its working in runtime.
So please, anyone give me the suggestion how can I solve this.
Thanks,
Nabil Ahmed | | Nabil Ahmed Monday, March 12, 2007 11:15 AM | I use ProgressBarRenderer class to draw the progressbar out on the datagridviewcell, and it worked great on both Vista and other platforms that supports .net 2.0or 3.0 and visual styles are enabled.
For the platforms visual styles are not supported, I still have to fall back to the bitmap way. | | Jun Wang Tuesday, June 26, 2007 8:48 PM | This is awesome, but how can I change the column type of a datagridview when I am creating the dataset dynamically?
szSql = szSql & "Select Column1, Column2, [Column1] * [Column2] / 100 As Colum3 From Broker_Data"
dsBkr = New DataSet
dvBkr = New DataView
Dim adBkr As New SqlDataAdapter(szSql, conSLX)
adBkr.Fill(dsBkr, "Broker_Data")
dvBkr.Table = dsBkr.Tables( "Broker_Data")
dgvBrokers.DataSource = dvBkr
dgvBrokers.Columns( "Column1").DefaultCellStyle.Format = "c"
dgvBrokers.Columns("Column2").DefaultCellStyle.Format = "c"
' So far so good
' Now how to set column3 to progress bar type
dgvBrokers.Columns("Column3).Type = DataGridViewProgressColumn
' Above line does not work
dgvBrokers.Refresh()
?????? | | Lloy Sanders Tuesday, September 25, 2007 5:50 PM | Hi Mark,
I am trying to get the code you provided for creating a Progress Bar column in a DataGridView working in a simple sample WinForm C# project.
I am working in Studio 2005 .Net 2.0 and that may be the reason the code is throwing an exception in Design Time.
Can you take a look or forward this to someone who might know?
Did the following: 1. Create new WinForm C# project 2. Created a new class and copied the code you provided into that class. 3. Changed the name space in your code to my project's name space... 4. Added a DataGridView to the WinForm 5. Added a Text column no problem. 6. Tried to add the new DataGridViewProgressColumn type to the grid and that causes the following exception: (Which I have to type by hand because the exception text is in a MessageBox show statement it appears)
The control System.Windows.Forms.DataGridView has thrown an unhandled exception in the designer and has been disabled.
Exception: Object reference not set to an instance of an object.
Stack trace: at System.Windows.Forms.DataGridViewCell.PaintWord(Graphics graphics, Rectangle clipBounds, Re3ctangle cellBounds, Int32 rowIndex, DataGridViewElementStates cellState, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts) in C:\Documents and Settings\Clint Carter\My Documents\Visual Studio 2005\ProgressBarInDataGridView\ProgressBarCell.cs: line 54
at System.Windows.Forms.DataGridViewRow.PaintCells(Graphics graphics, Rectangle clipBounds, Rectangle rowBounds, Int32 rowIndex, DataGridViewElementStates rowState, Boolean isFirstDisplayedRow, Boolean isLastVisibleRow, DataGridViewPaintParts paintParts)
at System.Windows.Forms.DataGridViewRow.Paint(Graphics graphics, Rectangle clipBounds, Rectangle rowBounds, Int32 rowIndex, DataGridViewElementStates rowState, Boolean isFirstDisplayedRow, Boolean isLastVisibleRow, DataGridViewPaintParts paintParts)
at System.Windows.Forms.DataGridView.PaintRows(.....) at System.Windows.Forms.DataGridView.PaintGrid(....)
etc...
That file is where I placed the code for the new cell/column type...
Here are the lines of code around that:
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) { Line 54: 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%. .....
So I thought perhaps "value" is null. I put a check around "value" before trying to assign it but I still get the same exception.
Any ideas?
Thanks,
Clint Carter
| | Clint Carter Friday, January 25, 2008 5:25 PM | I figured it out...I was close but my problem is that I didn't do a rebuild before trying...
Basically, the Paint event I need to test "value" for null before trying to assign...
And also down lower I needed to test "CurrentRow" before trying to access a method from it...
Here is the modified code...not fully tested...with no guarantee's that it even works...but it at least compiles for now...
//--------------------------------------------------------------------- //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 ProgressBarInDataGridView { public class DataGridViewProgressColumn : DataGridViewImageColumn { public DataGridViewProgressColumn() { CellTemplate = new DataGridViewProgressCell(); } } }
namespace ProgressBarInDataGridView { 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) { //============================================================= // WAS THROWING EXCPETION HERE AT DESIGN TIME IN STUDIO 2005 // ----> int progressVal = (int)value; // HERE IS THE CHANGE //============================================================= int progressVal = 0; if ( value != null ) progressVal = (int)value;
//===== END CHANGE ============================================
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 != null) { //============================================================= // WAS THROWING EXCPETION HERE AT DESIGN TIME IN STUDIO 2005... // SO I ADDED THE "if" CurrenRow != null above //============================================================= 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); } } } } }
| | Clint Carter Friday, January 25, 2008 5:36 PM |
just before your RED LINE 54, insert this code piece:
if ( object ==null || object.GetType() == typeof(DBNull )
return; | | Bluehunter Tuesday, April 01, 2008 9:22 AM | Here is an example of Creating a Custom Percentage Column inDataGridView Control
DataGridView Custom Percentage Column
Regards,
Arsalan Tamiz
http://arsalantamiz.blogspot.com | | Arsalan Tamiz Wednesday, April 23, 2008 10:40 AM | Hi Mark, I was working with datagridview control, with 4 databound columns, I want to add a checkboxcolumn. Which i'll use to pick the checked values from one datagridview into another. I figured that i need to copy those values 1st to a new table then bind that table to my control.
I cant actually get about the proper code to do this. Can you help me out.
Thanks!
Best Regards Chetan Sehgal
| | Chetansehgal Thursday, April 24, 2008 8:31 AM |
Hi,
Here i just confuing with this code. I have tried this but i am not getting. Actually my query is try to add progress bar controls in grid view control. Before this i want to explain one thing that is i have generated Tab controls dynamically and in this tab controls i am generating Grid view controls. In this grid view i am displaying the Id row, Url row and "Status" row. Ihave used data table and binded to the grid. But in row "Status", i want to add "Progress bar" control dynamically. Here i have written some code to work this functionality.
try
{
//To bind list view items to Tabcontrol start
//TabControl tc = new TabControl();
for (int i = 0; i < lbProjname.Items.Count; i++)
{
string item = lbProjname.Items .ToString();
if (!String.IsNullOrEmpty(item))
{
TabPage tabPage = new TabPage(item);
DataGridView dgv = new DataGridView();
//dgv.Columns.Add("Status");
dgv.Size = new Size(600, 200);
tbcProgressbar.TabPages.Add(tabPage);
DataTable dt = new DataTable("tbl");
DataColumn column = new DataColumn();
DataColumn column1 = new DataColumn();
DataColumn column2 = new DataColumn();
DataColumn column3 = new DataColumn();
DataRow row, row1, row2;
// Create new DataColumn, set DataType, ColumnName
//and add to DataTable.
//column = new DataColumn();
column.DataType = System. Type.GetType("System.Int32");
column.ColumnName = "ID";
column1.DataType = System. Type.GetType("System.String");
column1.ColumnName = "URL";
column2.DataType = System. Type.GetType("System.String");
column2.ColumnName = "Status";
//Add the Column to the DataColumnCollection.
dt.Columns.Add(column);
dt.Columns.Add(column1);
dt.Columns.Add(column2);
ImageSettings objImageSettings = new ImageSettings();
objImageSettings = ImageSettings.Restore(Application.StartupPath +"\\Projects\\"+ item + ".xml");
//int k;
//string filename = "C:\\Sites.txt";
//StreamReader sr19 = new StreamReader(filename);
//string file_names19 = sr19.ReadToEnd();
//file_names19 = file_names19.Replace("\r\n", "\r");
//string[] filenames19 = file_names19.Split('\r');
ProgressBar pbr = new ProgressBar();
for (int u = 0; u < objImageSettings.Sites.Count; u++)
{
row = dt.NewRow();
row[ "ID"] = u + 1;
row[ "URL"] = Convert.ToString(objImageSettings.Sites );
row[ "Status"] = "";
//row["Status"] = dgv.Controls.Add(pbr);
dt.Rows.Add(row);
}
//To get the files from Image settings
DataSet ds = new DataSet();
ds.Tables.Add(dt);
dgv.DataSource = ds.Tables[0];
tabPage.Controls.Add(dgv);
//dgv.Controls.Add(pbr);
//dgv.Rows.Add(pbr);
//dgv.CellFormatting +=new DataGridViewCellFormattingEventHandler(dgv_CellFormatting);
}
}
}
catch (Exception exc2)
{
MessageBox.Show("Projects are not there to generate the Thumbnails");
}
In above how can i add Progress bar controls, Please Find solution to my query, its most urjent. I am waiting for your reply.
Thanks,
Sahasra. | | Sahasra Monday, May 05, 2008 9:40 AM |
plz can u plz give me the code for 'SEARCH & PRINT" option for Visual Studio Web Developer 2005!
plz i really need it urgently!
thnx in advance!
Rushaa | | Rushaa Wednesday, May 14, 2008 5:26 PM | Hi Mark,
I am trying toset the value of the progress bar using a databound integer column(as suggested by u)whose value I amchanging in a loop as and when a file is getting downloaded.
But I am able to see only two values, 0 and 100being set in the progress bar.The reason for this is that thepaint event is not getting fired for the intermediate values set in the loop.
Also, while debugging I am able to see the intermediate values being set as intented.
Could you pls help me in finding a solution for the above problem?
I am attaching the code for ur reference.
Thanks in advance.
FileInfo uploadedFile = new FileInfo(uploadedFullPath);
if (uploadedFile.Exists)
{
Byte[] buffer = new Byte[5000];
FileStream ipStream = new FileStream(uploadedFullPath, FileMode.Open, FileAccess.Read, FileShare.Read);
long dataToRead = ipStream.Length;
while (dataToRead > 0)
{
ipStream.Read(buffer, 0, 5000);
string downloadFullPath = downloadPath + "\\" + drCheckedRow["File Name"].ToString();
FileStream opStream = new FileStream(downloadFullPath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
opStream.Write(buffer, 0, 5000);
opStream.Flush();
opStream.Close();
if (dataToRead > 0)
{
drCheckedRow[ "Status Value"] = ((float)(ipStream.Length - dataToRead) / ipStream.Length) * 100.0f; //Setting the value of progress bar.
drCheckedRow.AcceptChanges();
}
buffer = new Byte[5000];
dataToRead = dataToRead - 5000;
}
drCheckedRow[ "Status Value"] = 100.0f;
drCheckedRow.AcceptChanges();
ipStream.Close();
}
| | Shalini N Wednesday, December 10, 2008 9:26 AM | While Joel's code works really well on XP, it does not work with Vista. The progress bar is just grey with no progress indicator.
I modified his code in a way that it would work under Vista. Cheers
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;
if (value != null)
progressVal = (int)value;
else
progressVal = 0;
// Draws the cell grid
base.Paint(g, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, (paintParts & ~DataGridViewPaintParts.ContentForeground));
const int margin = 4;
ProgressBar pb = new ProgressBar();
int lHeight = cellBounds.Bottom - cellBounds.Top - (margin * 3);
int lWidth = ((cellBounds.Right - cellBounds.Left - (margin * 2)) * (progressVal) / 100);
pb.Height = cellBounds.Bottom - cellBounds.Top - (margin * 2);
pb.Width = cellBounds.Right - cellBounds.Left - (margin * 2);
pb.Top = 0;
pb.Left = 0;
if (pb.Width == 0)
pb.Width = 10;
pb.Value = 0;
Bitmap bmp = new Bitmap(pb.Width, pb.Height);
pb.DrawToBitmap(bmp, pb.ClientRectangle);
g.DrawImage(bmp, new Point(cellBounds.X + margin, cellBounds.Y + margin));
Rectangle myRectangle = new Rectangle(cellBounds.X + margin + 1, cellBounds.Y + 1 + (int)(margin * 1.333), lWidth - 1, lHeight);
if (myRectangle.Width == 0)
myRectangle.Width = 1;
LinearGradientBrush myLinearGradientBrush = new LinearGradientBrush(myRectangle, Color.LightGreen, Color.MediumSeaGreen, LinearGradientMode.Vertical);
myLinearGradientBrush.SetBlendTriangularShape((float).5);
g.FillRectangle(myLinearGradientBrush, myRectangle);
}
| | feszty Saturday, August 15, 2009 6:09 PM |
|