DataGridView 中彩色单元格的计数

Posted

技术标签:

【中文标题】DataGridView 中彩色单元格的计数【英文标题】:Counting of colored cell in DataGridView 【发布时间】:2019-03-20 07:40:26 【问题描述】:

我正在开发基于访问权限的 WinForm 应用程序。我的 DataGridView 中有彩色单元格(DateColumn)。我正在尝试计算如图所示的彩色单元格,并希望在标签的文本上反映彩色单元格的总数。我尝试了下面的代码,这些代码不计算我的 DataGridView 的彩色单元格总数,尽管计算总行数。具体问题可以通过this图片理解

我的代码如下:

private void metroGrid1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    

        if (this.metroGrid1.Columns[e.ColumnIndex].DataPropertyName == "Date 1")
            try
            
                var EMIDate1 = Convert.ToDateTime(metroGrid1.Rows[e.RowIndex].Cells["date1DataGridViewTextBoxColumn"].Value);

                for (int i = 0; i < metroGrid1.RowCount; i++)
                
                    if (EMIDate1 <= DateTime.Today)
                    
                        int countDarkRed = 0;
                        e.CellStyle.BackColor = Color.DarkRed;
                        e.CellStyle.ForeColor = Color.White;
                        foreach (DataGridViewRow row in this.metroGrid1.Rows)
                        

                            if (row.Cells["date1DataGridViewTextBoxColumn"].Style.BackColor == Color.DarkRed)
                            
                                countDarkRed++;
                            
                        
                        labelEMI.Text = "Total EMI due as on today:" + countDarkRed;
                    
                
            
            catch
            
            
    

【问题讨论】:

到底是什么问题?你希望有countDarkRed = 1,但它是0 我不明白你想要什么。你想计算有多少细胞有深红色背景吗?为什么不设置颜色的时候加个计数器呢? @NoChance 我想计算所有深红色单元格,还需要在 label.text 上显示这个数字 & 无法理解这一行的含义“为什么在设置颜色时不添加计数器?”。 @GiulioCaccin 我的问题是我无法计算所有深红色,你能告诉我为什么我应该有 countDarkRed = 1 尽管 DataGridView 开始时没有任何深红色单元格。 最简单的方法是在更改单元格颜色时增加计数器,而不是计算彩色单元格。 【参考方案1】:

简答 您想在网格的单元格中设置样式,而不仅仅是在单元格的当前格式化会话中。您为错误的 CellStyle 着色。直接访问网格单元格样式而不是使用事件单元格,您的代码将执行您想要的操作(在我的机器上测试):

        if (EMIDate1 <= DateTime.Today)
        
            this.metroGrid1[e.ColumnIndex, e.RowIndex].Style.BackColor = Color.DarkRed;
            this.metroGrid1[e.ColumnIndex, e.RowIndex].Style.ForeColor = Color.White;
        

长答案不要这样做

格式化事件将仅应用于可见单元格 由于控件/窗口太小而隐藏的行或列不会触发此代码 您将格式逻辑(颜色)与业务逻辑(过期日期)混合在一起 尝试在绑定网格之前执行此检查,或再次调用数据库 文档明确反对在单元格格式化事件中进行过多处理 https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.datagridview.cellformatting?view=netframework-4.7.2#remarks 每次出现窗口重绘、鼠标悬停等情况时都会执行此代码,从而使您的标签成为程序中最昂贵的标签之一 你应该只计算一次

完整的工作示例 创建一个只有一个 datagridview 和一个标签的窗体应用程序

    public Form1()
    
        InitializeComponent();

        dataGridView1.DataSource = new[]  
            new Title = "bella", Date1 = DateTime.Now.AddDays(1), 
            new Title = "ciao", Date1 = DateTime.Now.AddDays(12), 
            new Title = "bella", Date1 = DateTime.Now.AddDays(-1), 
            new Title = "ciao", Date1 = DateTime.Now.AddDays(-31), 
            new Title = "bella", Date1 = DateTime.Now.AddDays(11), 
            new  Title= "ciao", Date1 = DateTime.Today ,
            new  Title= "ciao", Date1 = DateTime.Today ,
            new  Title= "ciao", Date1 = DateTime.Today.AddDays(-7) ;

    

    private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    
        if (dataGridView1.Columns[e.ColumnIndex].DataPropertyName == "Date1")
        
            var date = dataGridView1.Rows[e.RowIndex].Cells["Date1"].Value as DateTime?;
            if (date.HasValue && date.Value <= DateTime.Today)
            
                dataGridView1[e.ColumnIndex, e.RowIndex].Style.BackColor = Color.DarkRed;
                dataGridView1[e.ColumnIndex, e.RowIndex].Style.ForeColor = Color.White;

            

            int countDarkRed = 0;
            foreach (DataGridViewRow row in dataGridView1.Rows)
            
                if (row.Cells["Date1"].Style.BackColor == Color.DarkRed)
                    countDarkRed++;
            
            label1.Text = $"dark = countDarkRed";
        
    

【讨论】:

先生,@Giulio 抱歉回复晚了。您的代码非常棒,可以完美运行。谢谢。你能帮我在上面的问题中编辑什么吗?这样我就可以提出更多的问题。截至目前,我无法再问任何问题。【参考方案2】:

在上一个案例中你出错的地方是,你只检查了第一个单元格并不断增加计数,现在你在上一个问题上混淆了我的 cmets。这是大纲:

有一个 if 循环来检查日期和改变颜色,一个 for 循环来计算改变颜色的单元格的数量

private void metroGrid1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)

    if (this.metroGrid1.Columns[e.ColumnIndex].DataPropertyName == "Date 1")
    
        try
        
            int countDarkRed = 0;
            var EMIDate1 = Convert.ToDateTime(metroGrid1.Rows[e.RowIndex].Cells["date1DataGridViewTextBoxColumn"].Value);

            //Checking whether we have to turn it red or not
            if (EMIDate1 <= DateTime.Today)
            
                e.CellStyle.BackColor = Color.DarkRed;
                e.CellStyle.ForeColor = Color.White;
            

            //Checking how many cells have turned red
            foreach(DataGridViewRow row in this.metroGrid1.Rows)
            
                if (row.Cells["date1DataGridViewTextBoxColumn"].Style.BackColor == Color.DarkRed)
                
                    countDarkRed++;
                
            
            labelEMI.Text = "Total EMI due as on today:" + countDarkRed;
        
        catch
        

        
    

【讨论】:

我对你的代码几乎没有改变 foreach(DataGridViewRow row in this.metroGrid1.Rows) if (row.Cells["date1DataGridViewTextBoxColumn"].Style.BackColor == Color.DarkRed) countDarkRed++; labelEMI.Text = "今天到期的总 EMI:" + countDarkRed;这是显示序列号。最后一个彩色单元格。您的实际代码没有显示对标签文本的计数。请帮忙 尝试调试看看哪里出错了,我看不出这段代码有什么问题,也许是有什么东西覆盖了这个数据,直到我看到完整的程序 此代码不起作用,您应该在设置样式时引用网格,而不是当前格式化会话单元格

以上是关于DataGridView 中彩色单元格的计数的主要内容,如果未能解决你的问题,请参考以下文章

DataGridView里单元格背景色无法设置

datagridview获取某个单元格的值

选定单元格的 Datagridview 平均值

DataGridView获取或者设置当前单元格的内容

如何获取 datagridview 单元格的 Style.BackColor

如何比较两个datagridview行单元格的值?