C# 根据条件更改datagridview单元格颜色

C# 根据条件更改datagridview单元格颜色,c#,winforms,datagridview,C#,Winforms,Datagridview,我已经将数据从数据库加载到datagridview,有两列target value和volume,其中volume>target value,volume单元格应为绿色,volume

我已经将数据从数据库加载到datagridview,有两列target value和volume,其中volume>target value,volume单元格应为绿色,volume
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;
            } 
你需要这样做

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; 
        }
    }
}
private void dataGridView1\u单元格格式(对象发送方,DataGridViewCellFormattingEventArgs e)
{
foreach(DataGridViewRow Myrow在dataGridView1.Rows中)
{//此处2个单元格为目标值,1个单元格为体积

if(Convert.ToInt32(Myrow.Cells[2].Value)我可能建议在每次调用CellFormating时,不要在每行上循环,因为每次需要刷新一行时都会调用它

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

Kyle和Simon的答案是对CPU资源的严重浪费。
CellFormatting
CellPaint
事件发生的次数太多,不应用于应用样式。以下是两种更好的方法:

如果DataGridView或至少决定单元格样式的列是只读的,则应在
RowsAdded
事件中更改行的DefaultCellStyle。添加新行时,此事件仅发生一次。此时应评估该条件,并在其中设置行的
DefaultCellStyle
。请注意,这甚至是错误的t在数据绑定的情况下也会出现

如果DataGridView或那些列允许编辑,则应使用
CellEndEdit
CommittedIt
事件来更改
DefaultCellStyle

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;
    }
}
这对我来说非常有效。即使一行发生了更改,同样的事件也会得到处理。

简单点

//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);
        }
    }
}
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;

}

看一看

假设您必须通过了解两件事来为某些单元格(不是该行的所有单元格)着色:

  • 列的名称或索引
  • 值,该值将位于单元格内部
  • 在这种情况下,您必须使用事件

    在我的情况下,我这样使用

    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;
           }
         }
    }
    
    例如,你需要给行中的一些单元格上色,比如###1、4、5和8,你必须使用单元格索引(从0开始)

    代码会像lok一样

     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;
        }
      }
    }
    

    令人惊讶的是,没有人提到一个简单的
    if
    语句可以确保每个格式(在第一行的第一列)只执行一次循环


    没有循环,它可以实现如下

    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);
            }
        }
    

    我知道这是一篇老文章,但我在2018年找到了自己的方法,所以也许其他人也会。在我看来,OP的方法(使用dgv_DataBindingComplete事件)比提供的任何答案都要好。在撰写本文时,所有答案都是使用paint事件或cellformatting事件编写的,这似乎效率低下

    OP是99%,他们所要做的就是循环他们的行,测试每行的单元格值,设置背景色、前景色或任何其他想要设置的属性

    请原谅vb.NET语法,但我认为它与C#足够接近,应该很清楚

    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
    

    这不是非常低效吗?因为每次重画任何单元格时都要对所有记录进行迭代。如果采用这种方法,则整个
    foreach
    子句不必位于CellFormatting处理程序中,但它应该是
    dataGridView1\U DataBindingComplete
    。或者使用var Myrow=dataGridView1.Rows[e.RowIndex]与执行循环(这是一个糟糕的解决方案)不同,该代码按每个单元格迭代所有行。此处的后期注释:此代码最好将值变暗,因为String=gv_DisplayData_Vertical.rows(e.RowIndex).Cells(“LevelID”).value.ToString()选择值大小写“1”e.CellStyle.BackColor=Color.DimGray退出选择结束选择代码在第三个if语句之后将更短、更易于阅读,并且选择大小写速度更快。它正在更改每个if语句的颜色cell@dotNET我知道这篇文章很老了,这是一个很好的观点。如果你只想改变改变的单个单元格,而不是整行,那该怎么办e只有绑定源正在更改,而单元格编辑事件尚未调用?@Ken:您仍然可以使用
    RowsAdded
    事件。在这种情况下,您应该使用所需单元格的
    Style
    属性,而不是使用行的
    DefaultCellStyle
    。如果需要根据数据源更改更改样式,您应该收听数据源本身引发的事件并更改其中的样式。例如,如果您使用
    数据表
    作为数据源,则可以收听
    数据表
    行更改
    列更改
    事件。而此代码可以回答问题,并提供有关y和/或该代码回答问题的方式提高了其长期价值。
    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);
            }
        }
    
    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
    
    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;
            }
        }
    }
    
    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;
    
                }
            }
        }