preethi
preethi

Reputation: 905

Changing datagridview cell color based on condition

I have loaded the data from database to datagridview and have two columns target value and volume where volume >target value that volume cell should be in green color and volume < target value then volume should be in red color. I tried it but I am not able to do it.

private void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
    if (dataGridView1.Rows.Count > 0 && dataGridView1.Columns.Count > 0)
    {
        foreach (DataGridViewRow r in dataGridView1.Rows)
        {
            if (Volume > target value)
            {
                cell.Style.BackColor = Color.AliceBlue;
            } 

Upvotes: 37

Views: 149297

Answers (13)

b0rg
b0rg

Reputation: 1897

Tis been awhile since I actually posted something on SO, but here we go.

Use _RowsAddedEvent to apply custom style to your grid cells, everything else will just eat too much CPU. And if you're asking this question these days, cpu cycles are important for you.

So, below are the codez to paint you cells depending on the value of underlying databounditem.

    private void grid_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
    {
        for ( int i = e.RowIndex; i <= e.RowIndex + e.RowCount - 1; i++)
        {
            var row = grid.Rows[i]; 
            var item = row.DataBoundItem as MovieViewerDataItem;
            if (item == null) continue;

            var cell = row.Cells["FullPath"]; 

            if ( item.FullPath.StartsWith("u:", StringComparison.InvariantCultureIgnoreCase))
            {
                cell.Style.BackColor = System.Drawing.ColorTranslator.FromHtml("#FFF2CC");
            }
            else if( item.FullPath.StartsWith("m:", StringComparison.InvariantCultureIgnoreCase))
            {
                cell.Style.BackColor = System.Drawing.ColorTranslator.FromHtml("#E2EFDA");
            }

        }
    }

Upvotes: 2

Rafael Hull
Rafael Hull

Reputation: 11

private void dataMain_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    {
        if (dataMain.Columns[e.ColumnIndex].Name == "colStatus")
        {
            if (int.Parse(e.Value.ToString()) == 2)
            {
                dataMain.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.OrangeRed;
                dataMain.Rows[e.RowIndex].DefaultCellStyle.ForeColor = Color.White;

            }
        }
    }

Upvotes: 1

AJEET YA
AJEET YA

Reputation: 21

private void dataGridView1_DataBindingComplete(object sender DataGridViewBindingCompleteEventArgs e)
{
    foreach (DataGridViewRow row in dataGridView1.Rows)
    {
        if (Convert.ToInt32(row.Cells["balaceAmount"].Value) == 0)
        {
            row.DefaultCellStyle.BackColor = Color.Yellow;
        }
        else
        {
            row.DefaultCellStyle.BackColor = Color.White;
        }
    }
}

Upvotes: 2

Scope Creep
Scope Creep

Reputation: 565

I know this is an old post, but I found my way here in 2018, so maybe someone else will too. In my opinion, the OP had a better approach (using dgv_DataBindingComplete event) than any of the answers provided. At the time of writing, all of the answers are written using paint events or cellformatting events which seems inefficient.

The OP was 99% of the way there, all they had to do was loop through their rows, test the cell value of each row, and set the BackColor, ForeColor, or whatever other property you want to set.

Please excuse the vb.NET syntax, but I think its close enough to C# that it should be clear.

Private Sub dgvFinancialResults_DataBindingComplete Handles dgvFinancialResults.DataBindingComplete
            Try
                Logging.TraceIt()
                For Each row As DataGridViewRow in dgvFinancialResults.Rows
                    Dim invoicePricePercentChange = CSng(row.Cells("Invoice Price % Change").Value)
                    Dim netPricePercentChange = CSng(row.Cells("Net Price % Change").Value)
                    Dim tradespendPricePercentChange = CSng(row.Cells("Trade Spend % Change").Value)
                    Dim dnnsiPercentChange = CSng(row.Cells("DNNSI % Change").Value)
                    Dim cogsPercentChange = CSng(row.Cells("COGS % Change").Value)
                    Dim grossProfitPercentChange = CSng(row.Cells("Gross Profit % Change").Value)


                    If invoicePricePercentChange > Single.Epsilon Then
                        row.Cells("Invoice Price % Change").Style.ForeColor = Color.Green
                    Else
                        row.Cells("Invoice Price % Change").Style.ForeColor = Color.Red
                    End If

                    If netPricePercentChange > Single.Epsilon Then
                        row.Cells("Net Price % Change").Style.ForeColor = Color.Green
                    Else
                        row.Cells("Net Price % Change").Style.ForeColor = Color.Red
                    End If

                    If tradespendPricePercentChange > Single.Epsilon Then
                        row.Cells("Trade Spend % Change").Style.ForeColor = Color.Green
                    Else
                        row.Cells("Trade Spend % Change").Style.ForeColor = Color.Red
                    End If

                    If dnnsiPercentChange > Single.Epsilon Then
                        row.Cells("DNNSI % Change").Style.ForeColor = Color.Green
                    Else
                        row.Cells("DNNSI % Change").Style.ForeColor = Color.Red
                    End If

                    If cogsPercentChange > Single.Epsilon Then
                        row.Cells("COGS % Change").Style.ForeColor = Color.Green
                    Else
                        row.Cells("COGS % Change").Style.ForeColor = Color.Red
                    End If

                    If grossProfitPercentChange > Single.Epsilon Then
                        row.Cells("Gross Profit % Change").Style.ForeColor = Color.Green
                    Else
                        row.Cells("Gross Profit % Change").Style.ForeColor = Color.Red
                    End If
                Next
            Catch ex As Exception
                Logging.ErrorHandler(ex)
            End Try
        End Sub

Upvotes: 0

dilipkumar katre
dilipkumar katre

Reputation: 166

Without looping it can be achived like below.

private void dgEvents_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e)
    {

        FormatRow(dgEvents.Rows[e.RowIndex]);

    }

private void FormatRow(DataGridViewRow myrow)
    {
        try
        {
            if (Convert.ToString(myrow.Cells["LevelDisplayName"].Value) == "Error")
            {
                myrow.DefaultCellStyle.BackColor = Color.Red;
            }
            else if (Convert.ToString(myrow.Cells["LevelDisplayName"].Value) == "Warning")
            {
                myrow.DefaultCellStyle.BackColor = Color.Yellow;
            }
            else if (Convert.ToString(myrow.Cells["LevelDisplayName"].Value) == "Information")
            {
                myrow.DefaultCellStyle.BackColor = Color.LightGreen;
            }
        }
        catch (Exception exception)
        {
            onLogs?.Invoke(exception.Message, EventArgs.Empty);
        }
    }

Upvotes: 1

Ramgy Borja
Ramgy Borja

Reputation: 2458

make it simple

private void dataGridView1_cellformatting(object sender,DataGridViewCellFormattingEventArgs e)
{
     var amount = (int)e.Value;

     // return if rowCount = 0
     if (this.dataGridView1.Rows.Count == 0)
         return;

     if (amount > 0)
         e.CellStyle.BackColor = Color.Green; 
     else
         e.CellStyle.BackColor = Color.Red;

}

take a look cell formatting

Upvotes: -1

clamchoda
clamchoda

Reputation: 4981

Surprised no one mentioned a simple if statement can make sure your loop only gets executed once per format (on the first column, of the first row).

    private void dgv_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    {
        // once per format
        if (e.ColumnIndex == 0 && e.RowIndex == 0)
        {
            foreach (DataGridViewRow row in dgv.Rows)
                if (row != null)
                    row.DefaultCellStyle.BackColor = Color.Red;
        }
    }

Upvotes: 0

Sumit Agrawal
Sumit Agrawal

Reputation: 1073

foreach (DataGridViewRow row in dgvWebData.Rows)
{
    if (Convert.ToString(row.Cells["IssuerName"].Value) != Convert.ToString(row.Cells["SearchTermUsed"].Value))
    {
        row.DefaultCellStyle.BackColor = Color.Yellow;
    }
    else
    {
        row.DefaultCellStyle.BackColor = Color.White;
    }
}

This Perfectly worked for me . even if a row is changed, same event takes care.

Upvotes: 3

NoWar
NoWar

Reputation: 37642

Let's say you have to color certain cell (not all cells of the row) by knowing two things:

  1. Name or index of the column.
  2. Value which is gonna be inside of the cell.

In thas case you have to use event CellFormatting

In my case I use like this

private void DgvTrucksMaster_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
     foreach (DataGridViewRow row in dgvTrucksMaster.Rows)
     {
       if (Convert.ToInt32(row.Cells["Decade1Hours"].Value) > 0)
       {
          row.Cells["Decade1Hours"].Style.BackColor = Color.LightGreen;
       }
       else if (Convert.ToInt32(row.Cells["Decade1Hours"].Value) < 0)
       {
          // row.DefaultCellStyle.BackColor = Color.LightSalmon; // Use it in order to colorize all cells of the row

          row.Cells["Decade1Hours"].Style.BackColor = Color.LightSalmon;
       }
     }
}

And result you can see here

enter image description here

So here you can access certain cell of the row in column by its name row.Cells["Decade1Hours"]

How do you know this name? Well in my case i create column of DataGridView like this.

var Decade1Hours = new DataGridViewTextBoxColumn()
{
   Name = "Decade1Hours",
   Width = 50,
   DataPropertyName = "Decade1Hours",
   ReadOnly = true,
   DefaultCellStyle = new DataGridViewCellStyle()
       {
        Alignment = DataGridViewContentAlignment.MiddleCenter,
        ForeColor = System.Drawing.Color.Black,
        Font = new Font(font, FontStyle.Bold),
        Format = "n2"
      },
   HeaderCell = new DataGridViewColumnHeaderCell()
      {
          Style = new DataGridViewCellStyle()
               {
                 Alignment = DataGridViewContentAlignment.MiddleCenter,
                 BackColor = System.Drawing.Color.Blue
               }
       }
};
Decade1Hours.HeaderText = "Дек.1";
dgvTrucksMaster.Columns.Add(Decade1Hours);

And well... you you need for instance colorize some of the cells in the row like ##1 4 5 and 8 you have to use cell index (it starts from 0).

And code will lok like

 private void DgvTrucksMaster_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
  foreach (DataGridViewRow row in dgvTrucksMaster.Rows)
  {
    if (Convert.ToInt32(row.Cells[1].Value) > 0 )
    {
      row.Cells[1].Style.BackColor = Color.LightGreen;
    }
  }
}

Upvotes: 6

Muhammad ElBarawi
Muhammad ElBarawi

Reputation: 1

//After Done Binding DataGridView Data
foreach(DataGridViewRow DGVR in DGV_DETAILED_DEF.Rows)
{
    if(DGVR.Index != -1)
    {
        if(DGVR.Cells[0].Value.ToString() == "البدلات")
        {
            CurrRType = "البدلات";
            DataGridViewCellStyle CS = DGVR.DefaultCellStyle;
            CS.BackColor = Color.FromArgb(0,175,100);
            CS.ForeColor = Color.FromArgb(0,32,15);

            CS.Font = new Font("Times New Roman",12,FontStyle.Bold);
            CS.SelectionBackColor = Color.FromArgb(0,175,100);
            CS.SelectionForeColor = Color.FromArgb(0,32,15);
            DataGridViewCellStyle LCS = DGVR.Cells[DGVR.Cells.Count - 1].Style;
            LCS.BackColor = Color.FromArgb(50,50,50);
            LCS.SelectionBackColor = Color.FromArgb(50,50,50);
        }
        else if(DGVR.Cells[0].Value.ToString() == "الإستقطاعات")
        {
            CurrRType = "الإستقطاعات";
            DataGridViewCellStyle CS = DGVR.DefaultCellStyle;
            CS.BackColor = Color.FromArgb(175,0,50);
            CS.ForeColor = Color.FromArgb(32,0,0);
            CS.Font = new Font("Times New Roman",12,FontStyle.Bold);
            CS.SelectionBackColor = Color.FromArgb(175,0,50);
            CS.SelectionForeColor = Color.FromArgb(32,0,0);
            DataGridViewCellStyle LCS = DGVR.Cells[DGVR.Cells.Count - 1].Style;
            LCS.BackColor = Color.FromArgb(50,50,50);
            LCS.SelectionBackColor = Color.FromArgb(50,50,50);
        }
    }
}

Upvotes: -1

dotNET
dotNET

Reputation: 35450

Kyle's and Simon's answers are gross waste of CPU resources. CellFormatting and CellPainting events occur far too many times and should not be used for applying styles. Here are two better ways of doing it:

If your DataGridView or at least the columns that decide cell style are read-only, you should change DefaultCellStyle of rows in RowsAdded event. This event occurs only once when a new row is added. The condition should be evaluated at that time and DefaultCellStyle of the row should be set therein. Note that this event occurs for DataBound situations too.

If your DataGridView or those columns allow editing, you should use CellEndEdit or CommitEdit events to change DefaultCellStyle.

Upvotes: 25

Simon
Simon

Reputation: 2362

I may suggest NOT looping over each rows EACH time CellFormating is called, because it is called everytime A SINGLE ROW need to be refreshed.

Private Sub dgv_DisplayData_Vertical_CellFormatting(sender As Object, e As DataGridViewCellFormattingEventArgs) Handles dgv_DisplayData_Vertical.CellFormatting
        Try

            If dgv_DisplayData_Vertical.Rows(e.RowIndex).Cells("LevelID").Value.ToString() = "6" Then

                e.CellStyle.BackColor = Color.DimGray
            End If
            If dgv_DisplayData_Vertical.Rows(e.RowIndex).Cells("LevelID").Value.ToString() = "5" Then
                e.CellStyle.BackColor = Color.DarkSlateGray
            End If
            If dgv_DisplayData_Vertical.Rows(e.RowIndex).Cells("LevelID").Value.ToString() = "4" Then
                e.CellStyle.BackColor = Color.SlateGray
            End If
            If dgv_DisplayData_Vertical.Rows(e.RowIndex).Cells("LevelID").Value.ToString() = "3" Then
                e.CellStyle.BackColor = Color.LightGray
            End If
            If dgv_DisplayData_Vertical.Rows(e.RowIndex).Cells("LevelID").Value.ToString() = "0" Then
                e.CellStyle.BackColor = Color.White
            End If

        Catch ex As Exception

        End Try

    End Sub

Upvotes: 31

Rohit
Rohit

Reputation: 10286

You need to do this

private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    foreach (DataGridViewRow Myrow in dataGridView1.Rows) 
    {            //Here 2 cell is target value and 1 cell is Volume
        if (Convert.ToInt32(Myrow .Cells[2].Value)<Convert.ToInt32(Myrow .Cells[1].Value))// Or your condition 
        {
            Myrow .DefaultCellStyle.BackColor = Color.Red; 
        }
        else
        {
            Myrow .DefaultCellStyle.BackColor = Color.Green; 
        }
    }
}

Meanwhile also take a look at Cell Formatting

Upvotes: 29

Related Questions