I would like to change the color of a particular row in my datagridview. The row should be changed to red when the value of columncell 7 is less than the value in columncell 10. Any suggestions on how to accomplish this?
19 Answers
You need to loop through the rows in the datagridview and then compare values of columns 7 and 10 on each row.
Try this:
foreach (DataGridViewRow row in vendorsDataGridView.Rows)
if (Convert.ToInt32(row.Cells[7].Value) < Convert.ToInt32(row.Cells[10].Value))
{
row.DefaultCellStyle.BackColor = Color.Red;
}
I was just investigating this issue (so I know this question was published almost 3 years ago, but maybe it will help someone... ) but it seems that a better option is to place the code inside the RowPrePaint
event so that you don't have to traverse every row, only those that get painted (so it will perform much better on large amount of data:
Attach to the event
this.dataGridView1.RowPrePaint
+= new System.Windows.Forms.DataGridViewRowPrePaintEventHandler(
this.dataGridView1_RowPrePaint);
The event code
private void dataGridView1_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e)
{
if (Convert.ToInt32(dataGridView1.Rows[e.RowIndex].Cells[7].Text) < Convert.ToInt32(dataGridView1.Rows[e.RowIndex].Cells[10].Text))
{
dataGridView1.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.Beige;
}
}
Something like the following... assuming the values in the cells are Integers.
foreach (DataGridViewRow dgvr in myDGV.Rows)
{
if (dgvr.Cells[7].Value < dgvr.Cells[10].Value)
{
dgvr.DefaultCellStyle.ForeColor = Color.Red;
}
}
untested, so apologies for any error.
If you know the particular row, you can skip the iteration:
if (myDGV.Rows[theRowIndex].Cells[7].Value < myDGV.Rows[theRowIndex].Cells[10].Value)
{
dgvr.DefaultCellStyle.ForeColor = Color.Red;
}
Some people like to use the Paint
, CellPainting
or CellFormatting
events, but note that changing a style in these events causes recursive calls. If you use DataBindingComplete
it will execute only once. The argument for CellFormatting
is that it is called only on visible cells, so you don't have to format non-visible cells, but you format them multiple times.
You can Change Backcolor
row by row using your condition.and this function call after applying Datasource
of DatagridView
.
Here Is the function for that.
Simply copy that and put it after Databind
private void ChangeRowColor()
{
for (int i = 0; i < gvItem.Rows.Count; i++)
{
if (BindList[i].MainID == 0 && !BindList[i].SchemeID.HasValue)
gvItem.Rows[i].DefaultCellStyle.BackColor = ColorTranslator.FromHtml("#C9CADD");
else if (BindList[i].MainID > 0 && !BindList[i].SchemeID.HasValue)
gvItem.Rows[i].DefaultCellStyle.BackColor = ColorTranslator.FromHtml("#DDC9C9");
else if (BindList[i].MainID > 0)
gvItem.Rows[i].DefaultCellStyle.BackColor = ColorTranslator.FromHtml("#D5E8D7");
else
gvItem.Rows[i].DefaultCellStyle.BackColor = Color.White;
}
}
private void dtGrdVwRFIDTags_DataSourceChanged(object sender, EventArgs e)
{
dtGrdVwRFIDTags.Refresh();
this.dtGrdVwRFIDTags.Columns[1].Visible = false;
foreach (DataGridViewRow row in this.dtGrdVwRFIDTags.Rows)
{
if (row.Cells["TagStatus"].Value != null
&& row.Cells["TagStatus"].Value.ToString() == "Lost"
|| row.Cells["TagStatus"].Value != null
&& row.Cells["TagStatus"].Value.ToString() == "Damaged"
|| row.Cells["TagStatus"].Value != null
&& row.Cells["TagStatus"].Value.ToString() == "Discarded")
{
row.DefaultCellStyle.BackColor = Color.LightGray;
row.DefaultCellStyle.Font = new Font("Tahoma", 8, FontStyle.Bold);
}
else
{
row.DefaultCellStyle.BackColor = Color.Ivory;
}
}
//for (int i= 0 ; i<dtGrdVwRFIDTags.Rows.Count - 1; i++)
//{
// if (dtGrdVwRFIDTags.Rows[i].Cells[3].Value.ToString() == "Damaged")
// {
// dtGrdVwRFIDTags.Rows[i].Cells["TagStatus"].Style.BackColor = Color.Red;
// }
//}
}
This is my solution to change color to dataGridView with bindingDataSource:
private void dataGridViewECO_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
if (e.ListChangedType != ListChangedType.ItemDeleted)
{
DataGridViewCellStyle green = this.dataGridViewECO.DefaultCellStyle.Clone();
green.BackColor = Color.Green;
DataGridViewCellStyle gray = this.dataGridViewECO.DefaultCellStyle.Clone();
gray.BackColor = Color.LightGray;
foreach (DataGridViewRow r in this.dataGridViewECO.Rows)
{
if (r.Cells[8].Value != null)
{
String stato = r.Cells[8].Value.ToString();
if (!" Open ".Equals(stato))
{
r.DefaultCellStyle = gray;
}
else
{
r.DefaultCellStyle = green;
}
}
}
}
}
If you bind to a (collection) of concrete objects, you can get the that concrete object via the DataBoundItem property of the row. (To avoid check for magic strings in the cell and using "real" properties of the object)
Skeleton example below:
DTO/POCO
public class Employee
{
public int EmployeeKey {get;set;}
public string LastName {get;set;}
public string FirstName {get;set;}
public bool IsActive {get;set;}
}
Binding to the datagridview
private void BindData(ICollection<Employee> emps)
{
System.ComponentModel.BindingList<Employee> bindList = new System.ComponentModel.BindingList<Employee>(emps.OrderBy(emp => emp.LastName).ThenBy(emp => emp.FirstName).ToList());
this.dgvMyDataGridView.DataSource = bindList;
}
then the event handler and getting the concrete object (instead of a DataGridRow and/or cells)
private void dgvMyDataGridView_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e)
{
Employee concreteSelectedRowItem = this.dgvMyDataGridView.Rows[e.RowIndex].DataBoundItem as Employee;
if (null != concreteSelectedRowItem && !concreteSelectedRowItem.IsActive)
{
dgvMyDataGridView.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.LightGray;
}
}
Works on Visual Studio 2010. (I tried it and it works!) It will paint your entire row.
- Create a button for the
datagridview
. - Create a
CellClick
event and put the next line of code inside of it.
if (dataGridView3.Columns[e.ColumnIndex].Index.Equals(0)
{
dataGridView3.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.Beige;
}
You have not mentioned how value is changed. I have used similar functionality when user is entering value. i.e. entering and leaving edit mode.
Using CellEndEdit event of datagridview.
private void dgMapTable_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
double newInteger;
if (double.TryParse(dgMapTable[e.ColumnIndex,e.RowIndex].Value.ToString(), out newInteger)
{
if (newInteger < 0 || newInteger > 50)
{
dgMapTable[e.ColumnIndex, e.RowIndex].Style.BackColor = Color.Red;
dgMapTable[e.ColumnIndex, e.RowIndex].ErrorText
= "Keep value in Range:" + "0 to " + "50";
}
}
}
You may add logic for clearing error notification in a similar way.
if in your case, if data is loaded programmatically, then CellLeave event can be used with same code.
Just a note about setting DefaultCellStyle.BackColor
...you can't set it to any transparent value except Color.Empty
. That's the default value. That falsely implies (to me, anyway) that transparent colors are OK. They're not. Every row I set to a transparent color just draws the color of selected-rows.
I spent entirely too much time beating my head against the wall over this issue.
If you are the second dumbest developer on the planet (me being the dumbest), all of the above solutions seem to work: CellFormatting, DataSourceChanged, and RowPrePaint. I prefer RowPrePaint.
I struggled with this (for way too long) because I needed to override my SelectionBackColor and SelectionForeColor instead of BackColor and ForeColor as I was changing the selected row.
int counter = gridEstimateSales.Rows.Count;
for (int i = 0; i < counter; i++)
{
if (i == counter-1)
{
//this is where your LAST LINE code goes
//row.DefaultCellStyle.BackColor = Color.Yellow;
gridEstimateSales.Rows[i].DefaultCellStyle.BackColor = Color.Red;
}
else
{
//this is your normal code NOT LAST LINE
//row.DefaultCellStyle.BackColor = Color.Red;
gridEstimateSales.Rows[i].DefaultCellStyle.BackColor = Color.White;
}
}
like this?
if (readmesaj.durum11 == "Under")
{
dataGridView1.Rows[i].Cells[1].Style.BackColor = Color.Yellow;
}
if (readmesaj.durum11 == "Pass")
{
dataGridView1.Rows[i].Cells[1].Style.BackColor = Color.Green;
}
if (readmesaj.durum11 == "Over")
{
dataGridView1.Rows[i].Cells[1].Style.BackColor = Color.Red;
}