在DataGridView中对彩色单元格进行计数

时间:2019-03-20 07:40:27

标签: c# datagridview

我正在开发基于访问的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
            {
            }
    }

2 个答案:

答案 0 :(得分: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}";
        }
    }

答案 1 :(得分:0)

在前一个案例中您出错的地方是,您仅检查第一个单元格并不断增加计数,现在您已经混淆了我对上一个问题的评论。这是大纲:

有一个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
        {

        }
    }
}