如何根据条件更改 DataGridView 的行颜色以检查日期是不是过期

Posted

技术标签:

【中文标题】如何根据条件更改 DataGridView 的行颜色以检查日期是不是过期【英文标题】:How to change a row color of DataGridView based on Condition to check if Date Expired如何根据条件更改 DataGridView 的行颜色以检查日期是否过期 【发布时间】:2021-10-08 11:08:17 【问题描述】:

我想要实现的是根据下面代码中提到的条件动态更改datagridview 行的颜色,这意味着如果到期日期大于当前日期,这意味着它已过期,那么行将其颜色更改为红色 如果还有 30 天在到期而不是变黄

private void ViewMedicine_DataGrid_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    
        
        if (Dont know what to write here)
        
            foreach (DataGridViewRow row in ViewMedicine_DataGrid.Rows) 
            
                row.DefaultCellStyle.BackColor = Color.Red;
                row.DefaultCellStyle.ForeColor = Color.White;

            
        
    

【问题讨论】:

我对你的陈述感到困惑……“如果 E_Date(到期日)大于当前日期,则意味着它已过期”……? ... 这似乎倒退了,应该是“如果 E_Date 小于当前日期,则 E_Date 已过期” ...我错过了什么吗?在任何一种情况下,检查日期是在“当前日期”之前还是之后都会看起来像……if (E_Date.Date < DateTime.Now.Date) // E_Date is expired ; @JohnG 我已经对问题进行了更改,因为之前由于 SQL 查询部分而造成混淆,并使其变得简单,因此不会混淆。 @JohnG 在我解决了这个问题时也发布了答案请检查 您可能需要注意...将代码放入网格RowPrePaint 事件意味着即使日期没有更改,代码也会检查日期并为行着色。示例...当用户“滚动”网格时,网格RowPrePaint 事件将触发并检查日期并为行着色,当它已经是正确的颜色时。您应该小心将代码放入哪个网格事件,以避免不必要地执行它。这可能会导致 UI 迟缓。 另外,如果日期在当前日期之后,我仍然不明白如何“过期”。这对我来说似乎倒退了……但是,如果它对你有用,那就去吧。 【参考方案1】:

为了实现您要查找的内容,您可以使用两个嵌套的 for,一个循环查询 (DataTable MrkExp) 的结果,一个循环循环您的 dataGridView 中包含的值。

假设您的数据库表和 dataGridView 都有一个唯一 ID 或字段,您可以检查它们是否相等。

要实现这一点:

for (int i = 0; i < ViewMedicine_DataGrid.Rows.Count; i++)
                
                    for (int j = 0; j < MrkExp.Rows.Count; j++)
                    
                        if (ViewMedicine_DataGrid.Rows[i].Cells[0].Value != null)
                        
                            if (ViewMedicine_DataGrid.Rows[i].Cells[0].Value == MrkExp.Rows[j]["UNIQUE_FIELD"])
                            
                                ViewMedicine_DataGrid.Rows[i].DefaultCellStyle.BackColor = Color.Red;
                                ViewMedicine_DataGrid.Rows[i].DefaultCellStyle.ForeColor = Color.White;
                            
                        
                    
                

如果您没有唯一字段或主要字段,请考虑更新您的问题以显示您的表结构。

【讨论】:

在我解决了这个问题时发布了答案请检查【参考方案2】:

最后,在对代码进行了一些头脑风暴并进行了一些研究之后,我成功地获得了预期的结果。这是我使用RowPrePaint 事件编写的代码

private void ViewMedicine_DataGrid_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e)
        
            var ExpiryDate = Convert.ToDateTime(ViewMedicine_DataGrid.Rows[e.RowIndex].Cells[7].Value);
            var TodayDate = DateTime.Today;
            var Expired = ExpiryDate >= TodayDate;
            var ExpiredToBe = ExpiryDate >= TodayDate.AddDays(-30);
            if (Expired)
            
                ViewMedicine_DataGrid.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.Red;
            
            else if (ExpiredToBe)
            
                ViewMedicine_DataGrid.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.Yellow;
            
        

在我使用错误的CellFormatting 事件并创建RowPrePaint 事件之前,在if 语句之前声明要在if 语句中使用的变量,我使用的代码显示了其余部分。它就像一个魅力

【讨论】:

【参考方案3】:

我的建议是为此使用event DataGridViewCell.CellFormatting。每当需要格式化单元格 [x, y] 时都会调用它。

使用 DataBinding 轻松访问行中的数据

我不知道您在 DataGridView 中显示什么样的项目,让我们假设它是价格优惠的集合。每个报价都有一个有效期:

class PriceOffer

    public DateTime ExpiryDate get; set;
    ...

您在某处告诉需要显示 PriceOffer 的哪些列。可能在构造函数中:

InitializeComponent();

this.ColumnStartDate.DataPropertyName = nameof(PriceOffer.StartDate);
this.ColumnExpiryDate.DataPropertyName = nameof(PriceOffer.ExpiryDate);
this.ColumnPrice.DataPropertyName = nameof(PriceOffer.Price);
...

您还有一个属性来获取您的 PriceOffers 初始集合:

IEnumerable<PriceOffer> FetchPriceOffersToDisplay(...)

    return ...

当然还有将这些 PriceOffers 附加到 DataGridView 的属性

BindingList<PriceOffer> DisplayedPriceOffers

    get => return (BindingList<PriceOffer>)this.dataGridView1.DataSource;
    set => this.dataGridView1.DataSource = value;

加载表单时初始化

void OnFormLoad(object sender, ...)

    this.DisplayedPriceOffers = new BindingList<PriceOffer>(
        this.FetchPriceOffersToDisplay().ToList());

操作员所做的所有更改:添加/删除/编辑 PriceOffers 都会在this.DisplayedPriceOffers 中自动更新。

回到你的问题

private void dataGridView1_CellFormatting(object sender, 
    DataGridViewCellFormattingEventArgs e)


    DataGridViewRow row = this.dataGridView1.Rows[e.RowIndex];
    PriceOffer priceOffer = (PriceOffer)row.DataboundItem;
    
    if (DateTime.Today > priceOffer.ExpiryDate)
    
        this.ColorRowExpired(row);
    
    else
    
        this.ColorRowNotExpired(row);
    


void ColorRowExpired(DataGridViewRow row)

    foreach (DataGridViewCell cell in row.Cells)
    
        cell.BackColor = ExpiredCellBackColor;
        ...
    

【讨论】:

以上是关于如何根据条件更改 DataGridView 的行颜色以检查日期是不是过期的主要内容,如果未能解决你的问题,请参考以下文章

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

选中复选框后如何更改datagridview中的行颜色

如何使用来自底层绑定源的行对 datagridview 行执行样式更改?

winform datagridview如何根据内容的行数自动改变高度

如何根据严重性更改数据网格中的行颜色?

在子窗体中DataGridView中填充数据后根据我的要求把符合要求的用别的颜色显示出来,怎么不能显示