【问题标题】:Changing datagridview cell color based on condition根据条件更改 datagridview 单元格颜色
【发布时间】:2013-10-23 04:50:31
【问题描述】:

我已将数据从数据库加载到 datagridview 并有两列目标值和体积,其中体积 > 目标值,体积单元格应为绿色,体积

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

【问题讨论】:

    标签: c# winforms datagridview


    【解决方案1】:

    我可能建议在每次调用 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
    

    【讨论】:

    • 此处延迟评论:此代码会更好 Dim value As String = gv_DisplayData_Vertical.Rows(e.RowIndex).Cells("LevelID").Value.ToString() Select Value case "1" e .CellStyle.BackColor = Color.DimGray Exit Select EndSelect 代码会更短,更易于阅读,并且在第三个 if 语句之后选择 case 更快。
    • 它正在改变每个单元格的颜色
    【解决方案2】:

    你需要这样做

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

    同时也看看Cell Formatting

    【讨论】:

    • 这会不会非常低效?由于您每次重绘任何单元格时都会遍历所有记录。如果您采用这种方法,则整个 foreach 子句不必位于 CellFormatting 处理程序中,但应该是 dataGridView1_DataBindingComplete
    • 或使用 var Myrow = dataGridView1.Rows[e.RowIndex] 而不是循环
    • 这是一个糟糕的解决方案,代码按每个单元格迭代所有行。
    【解决方案3】:

    Kyle 和 Simon 的回答严重浪费了 CPU 资源。 CellFormattingCellPainting 事件发生的次数太多,不应用于应用样式。这里有两种更好的方法:

    如果您的 DataGridView 或至少决定单元格样式的列是只读的,您应该在 RowsAdded 事件中更改行的 DefaultCellStyle。此事件仅在添加新行时发​​生一次。那时应该评估条件并且应该在其中设置行的DefaultCellStyle。请注意,此事件也会在 DataBound 情况下发生。

    如果您的 DataGridView 或那些列允许编辑,您应该使用 CellEndEditCommitEdit 事件来更改 DefaultCellStyle

    【讨论】:

    • @dotNET 我知道帖子已经过时了——而且是一个很好的观点。如果您只想更改已更改的单个单元格而不是整行怎么办?并且假设只有绑定源被更改并且单元格编辑事件没有被调用?
    • @Ken:您仍然可以使用RowsAdded 事件。而不是使用行的DefaultCellStyle,在这种情况下,您应该使用所需单元格的Style 属性。如果你需要根据数据源的变化来改变风格,你应该监听数据源本身引发的事件并改变其中的风格。例如,如果您使用DataTable 作为数据源,则可以监听DataTableRowChangedColumnChanged 事件。
    【解决方案4】:

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

    1. 列的名称或索引。
    2. 将在单元格内的值。

    在这种情况下,您必须使用事件CellFormatting

    就我而言,我是这样使用的

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

    你可以在这里看到结果

    因此,您可以在此处按名称访问列中行的某些单元格 row.Cells["Decade1Hours"]

    你怎么知道这个名字的? 好吧,就我而言,我像这样创建 DataGridView 列。

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

    而且...您需要例如为行中的某些单元格着色,例如 ##1 4 5 和 8,您必须使用单元格索引(它从 0 开始)。

    代码看起来像

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

    【讨论】:

      【解决方案5】:
      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;
          }
      }
      

      这对我来说非常有用。即使更改了一行,也会处理相同的事件。

      【讨论】:

        【解决方案6】:

        无需循环即可实现如下。

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

        【讨论】:

          【解决方案7】:
          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;
                  }
              }
          }
          

          【讨论】:

          • 虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。
          【解决方案8】:
          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;
          
                      }
                  }
              }
          

          【讨论】:

            【解决方案9】:

            自从我在 SO 上实际发布了一些东西以来已经有一段时间了,但我们开始吧。

            使用 _RowsAddedEvent 将自定义样式应用于您的网格单元格,其他所有内容都会占用过多的 CPU。如果你最近问这个问题,CPU 周期对你来说很重要。

            所以,下面是根据底层数据绑定项的值绘制单元格的代码。

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

            【讨论】:

              【解决方案10】:

              很惊讶没有人提到一个简单的if 语句可以确保您的循环仅在每种格式中执行一次(在第一行的第一列上)。

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

              【讨论】:

                【解决方案11】:

                我知道这是一篇旧帖子,但我在 2018 年找到了自己的方式,所以也许其他人也会。在我看来,OP 比提供的任何答案都有更好的方法(使用 dgv_DataBindingComplete 事件)。在撰写本文时,所有答案都是使用绘制事件或单元格格式化事件编写的,这似乎效率低下。

                OP 已经完成了 99%,他们所要做的就是遍历他们的行,测试每一行的单元格值,并设置 BackColor、ForeColor 或任何其他您想要设置的属性。

                请原谅 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
                

                【讨论】:

                  【解决方案12】:
                  //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);
                          }
                      }
                  }
                  

                  【讨论】:

                    【解决方案13】:

                    简单一点

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

                    看看cell formatting

                    【讨论】:

                      猜你喜欢
                      • 2023-04-06
                      • 1970-01-01
                      • 2017-02-05
                      • 1970-01-01
                      • 2017-07-03
                      • 1970-01-01
                      • 1970-01-01
                      • 2013-04-12
                      相关资源
                      最近更新 更多