rwheeler23
asked on
How to set color of row inside a datagridview using C# based on a value in the row.?
I have placed a datagridview called dgvTransferPOs onto a Winform using C#. What is being displayed is a list of purchase order numbers resulting from a SQL query. One of the columns in the query is called IsClosed. What I need is to change the color of the row to red if IsClosed = 1 otherwise use the default color if IsClosed =0. The dgv displays 10 records at a time. So if there are 20 records and the user scrolls down, the color needs to move as the slider is moved.
ASKER
So in my case where I may be displaying 10 purchase orders and the sixth PO is closed (IsClosed=1) only the sixth line will be red? I see what you are doing. You are applying this as the form loads and checking the value of IsClosed.
You got it. Just make sure you use the correct column index. ;)
-saige-
-saige-
ASKER
Please excuse my ignorance, but my data is sitting in a dataset as a result of executing a SQL query. How do I translate your code below to use what is sitting in my dataset?
private void OnLoad(object sender, System.EventArgs e)
{
dataGridView1.DataSource = Enumerable.Range(0, 10).Select(i => new { Id = i, Name = $"Name{i}", Birthdate = DateTime.Now.AddMonths(-(i * 9)), IsWorking = (i & 1) == 0 }).ToList();
}
private void OnLoad(object sender, System.EventArgs e)
{
dataGridView1.DataSource = Enumerable.Range(0, 10).Select(i => new { Id = i, Name = $"Name{i}", Birthdate = DateTime.Now.AddMonths(-(i
}
ASKER
This is what I have so far. No colors are changing.
private void dgvTransferPOs_CellFormatt ing(object sender, DataGridViewCellFormatting EventArgs e)
{
if (e.ColumnIndex == 4)
{
MessageBox.Show("Her I am!");
var grid = sender as DataGridView;
if (Convert.ToBoolean(grid.Ro ws[e.RowIn dex].Cells [e.ColumnI ndex].Valu e))
{
grid.Rows[e.RowIndex].Defa ultCellSty le.BackCol or = Color.Red;
}
}
}
private void frmJobTrnPOLookup_Load(obj ect sender, EventArgs e)
{
//dgvTransferPOs.DataSourc e = Enumerable.Range(0, 10).Select(i => new { Id = i, txtp, VENDNAME, PODATE, REQDATE).ToList();
}
private void dgvTransferPOs_CellFormatt
{
if (e.ColumnIndex == 4)
{
MessageBox.Show("Her I am!");
var grid = sender as DataGridView;
if (Convert.ToBoolean(grid.Ro
{
grid.Rows[e.RowIndex].Defa
}
}
}
private void frmJobTrnPOLookup_Load(obj
{
//dgvTransferPOs.DataSourc
}
ASKER
There are four fields in the grid. The fifth field is the IsClosed column which I have set Visible to false. I can watch it go through each column and then the next row but the colors never change. I did set e.ColumnIndex == 5
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Interesting, I have changed the IsClosed field to now read "OPEN" or "CLOSED". I will make this column visible and then adjust the code to look for "CLOSED" for red otherwise white.
ASKER
OK, I am real close with this. If I put a Messagebox.Show inside this as it displays each line they are either red or white. However, take out the messagebox and I can see the values in the grid for a split second but then I get the message "object not set to an instance of an object". It appears to run past the grid. How do I prevent this?
private void dgvTransferPOs_CellFormatt ing(object sender, DataGridViewCellFormatting EventArgs e)
{
if (e.ColumnIndex == 4)
{
var grid = sender as DataGridView;
if (grid.Rows[e.RowIndex].Cel ls[e.Colum nIndex].Va lue.ToStri ng() == "CLOSED")
{
grid.Rows[e.RowIndex].Defa ultCellSty le.BackCol or = Color.Red;
}
else
{
grid.Rows[e.RowIndex].Defa ultCellSty le.BackCol or = Color.White;
}
}
}
private void dgvTransferPOs_CellFormatt
{
if (e.ColumnIndex == 4)
{
var grid = sender as DataGridView;
if (grid.Rows[e.RowIndex].Cel
{
grid.Rows[e.RowIndex].Defa
}
else
{
grid.Rows[e.RowIndex].Defa
}
}
}
You should debug it in order to find out what is give the object reference exception. If it were out of bounds you would get an error saying such.
-saige-
-saige-
ASKER
Debugging told me nothing useful. I see if go through 21 rows x 5 columns. It gets to the last column on the last row and crashes. Do I have this on the correct event?
private void dgvTransferPOs_CellFormatt ing(object sender, DataGridViewCellFormatting EventArgs e)
{
if (e.ColumnIndex == 4)
{
var grid = sender as DataGridView;
foreach (var row in grid.Rows.Cast<DataGridVie wRow>())
{
if (grid.Rows[e.RowIndex].Cel ls[e.Colum nIndex].Va lue.ToStri ng() == "CLOSED")
{
grid.Rows[e.RowIndex].Defa ultCellSty le.BackCol or = Color.Red;
}
else
{
grid.Rows[e.RowIndex].Defa ultCellSty le.BackCol or = Color.White;
}
}
}
}
private void dgvTransferPOs_CellFormatt
{
if (e.ColumnIndex == 4)
{
var grid = sender as DataGridView;
foreach (var row in grid.Rows.Cast<DataGridVie
{
if (grid.Rows[e.RowIndex].Cel
{
grid.Rows[e.RowIndex].Defa
}
else
{
grid.Rows[e.RowIndex].Defa
}
}
}
}
This event should work, if anything, you could try the DataBindingComplete event and go through the rows as I demonstrated above.
-saige-
-saige-
ASKER
Saige, thank you so much for your patience with me on this. Thanks to your help I now have working code. What I have below works perfectly. If I may ask one more question?
What does [Browsable(false)] in the class do?
[Browsable(false)]
public bool IsClosed { get; set; }
private void dgvTransferPOs_DataBinding Complete(o bject sender, DataGridViewBindingComplet eEventArgs e)
{
var grid = sender as DataGridView;
if (Equals(grid, dgvTransferPOs))
{
// Using a well defined column
foreach (var row in grid.Rows.Cast<DataGridVie wRow>())
{
// IsClosed is not visible, but we can still access the value
if (Convert.ToBoolean(row.Cel ls[5].Valu e))
{
row.DefaultCellStyle.BackC olor = Color.Red;
}
}
}
else
{
// Using a well defined type
foreach (var row in grid.Rows.Cast<DataGridVie wRow>())
{
// IsWorking is not visible, but we can still access the value
if ((row.DataBoundItem as PODOC).IsClosed)
{
row.DefaultCellStyle.BackC olor = Color.Red;
}
//else
//{
// row.DefaultCellStyle.BackC olor = Color.White;
//}
}
}
}
class PODOC
{
public string PONUM { get; set; }
public DateTime PODATE { get; set; }
public DateTime REQDATE { get; set; }
public string POSTATUS { get; set; }
[Browsable(false)]
public bool IsClosed { get; set; }
}
What does [Browsable(false)] in the class do?
[Browsable(false)]
public bool IsClosed { get; set; }
private void dgvTransferPOs_DataBinding
{
var grid = sender as DataGridView;
if (Equals(grid, dgvTransferPOs))
{
// Using a well defined column
foreach (var row in grid.Rows.Cast<DataGridVie
{
// IsClosed is not visible, but we can still access the value
if (Convert.ToBoolean(row.Cel
{
row.DefaultCellStyle.BackC
}
}
}
else
{
// Using a well defined type
foreach (var row in grid.Rows.Cast<DataGridVie
{
// IsWorking is not visible, but we can still access the value
if ((row.DataBoundItem as PODOC).IsClosed)
{
row.DefaultCellStyle.BackC
}
//else
//{
// row.DefaultCellStyle.BackC
//}
}
}
}
class PODOC
{
public string PONUM { get; set; }
public DateTime PODATE { get; set; }
public DateTime REQDATE { get; set; }
public string POSTATUS { get; set; }
[Browsable(false)]
public bool IsClosed { get; set; }
}
So Browsable is an attribute that tells consumers whether they should display the property.
The DataGridView control will not display properties that have the Browsable(false) attribute defined on them.
-saige-
The DataGridView control will not display properties that have the Browsable(false) attribute defined on them.
-saige-
ASKER
Thank you for your invaluable assistance.
Form1.cs -
Open in new window
Form1.Designer.cs -Open in new window
Produces the following output --saige-