根据条件更改 datagridview 单元格颜色
Posted
技术标签:
【中文标题】根据条件更改 datagridview 单元格颜色【英文标题】:Changing datagridview cell color based on condition 【发布时间】: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;
【问题讨论】:
【参考方案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 资源。 CellFormatting
和 CellPainting
事件发生的次数太多,不应用于应用样式。这里有两种更好的方法:
如果您的 DataGridView 或至少决定单元格样式的列是只读的,您应该在 RowsAdded
事件中更改行的 DefaultCellStyle。此事件仅在添加新行时发生一次。那时应该评估条件并且应该在其中设置行的DefaultCellStyle
。请注意,此事件也会在 DataBound 情况下发生。
如果您的 DataGridView 或那些列允许编辑,您应该使用 CellEndEdit
或 CommitEdit
事件来更改 DefaultCellStyle
。
【讨论】:
@dotNET 我知道帖子已经过时了——而且是一个很好的观点。如果您只想更改已更改的单个单元格而不是整行怎么办?并且假设只有绑定源被更改并且单元格编辑事件没有被调用? @Ken:您仍然可以使用RowsAdded
事件。而不是使用行的DefaultCellStyle
,在这种情况下,您应该使用所需单元格的Style
属性。如果你需要根据数据源的变化来改变风格,你应该监听数据源本身引发的事件并改变其中的风格。例如,如果您使用DataTable
作为数据源,则可以监听DataTable
的RowChanged
或ColumnChanged
事件。【参考方案4】:
假设您必须通过了解两件事来为某个单元格(不是该行的所有单元格)着色:
-
列的名称或索引。
将在单元格内的值。
在这种情况下,您必须使用事件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
【讨论】:
以上是关于根据条件更改 datagridview 单元格颜色的主要内容,如果未能解决你的问题,请参考以下文章
ReactJS 7 - 如何根据其值有条件地仅更改表格单元格(而不是行)的背景颜色?