计算总和-Datagridview的CellFormating事件性能太慢

时间:2019-02-20 09:19:04

标签: c# .net winforms datagridview

我正在使用dataGridView1_CellFormatting对每个列求和。但这使我的datagridview滚动非常慢。特别是当我有大量数据时。

 private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    {

        Decimal sum = 0, sum2 = 0, sum3 = 0;
        for (int i = 0; i < CustomersGrid.Rows.Count; ++i)
        {

                sum += Convert.ToDecimal(CustomersGrid.Rows[e.RowIndex].Cells[7].Value);
                sum2 += Convert.ToDecimal(CustomersGrid.Rows[e.RowIndex].Cells[6].Value);
                sum3 += Convert.ToDecimal(CustomersGrid.Rows[e.RowIndex].Cells[8].Value);
        }

        Quantitytxt.Text = sum2.ToString() + "   ";
        Sumtxt.Text = string.Format("{0:0.00}", sum).Replace(",", ".") + "€" + "   ";
        DiscountSumtxt.Text = string.Format("{0:0.00}", sum3).Replace(",", ".") + "€" + "   ";

    }

有没有更有效的方法呢?仅当我将获得此单元格时才求和的示例?或者是否还有其他事件或方法可用于此?我也尝试过这个。

 private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    {

        Decimal sum = 0, sum2 = 0, sum3 = 0;
        for (int i = 0; i < CustomersGrid.Rows.Count; ++i)
        {
            if (e.ColumnIndex == 7 || e.ColumnIndex == 6 || e.ColumnIndex == 8)
            {
                sum += Convert.ToDecimal(CustomersGrid.Rows[e.RowIndex].Cells[7].Value);
                sum2 += Convert.ToDecimal(CustomersGrid.Rows[e.RowIndex].Cells[6].Value);
                sum3 += Convert.ToDecimal(CustomersGrid.Rows[e.RowIndex].Cells[8].Value);
            }
        }
        Quantitytxt.Text = sum2.ToString() + "   ";
        Sumtxt.Text = string.Format("{0:0.00}", sum).Replace(",", ".") + "€" + "   ";
        DiscountSumtxt.Text = string.Format("{0:0.00}", sum3).Replace(",", ".") + "€" + "   ";

    }

它看起来似乎没有更好的性能,但是在滚动datagridview时仍然很慢。

2 个答案:

答案 0 :(得分:3)

documentations中已经提到:

  

每次绘制每个单元格时都会发生CellFormatting事件,因此   您在处理此事件时应避免冗长的处理。这个   检索单元格FormattedValue或其单元格时也会发生此事件   调用GetFormattedValue方法。

对所有像元处理12-24对于计算CellFormatting来说是太多了。

如果您使用的Sum之类的引发事件DataSource的{​​{1}},要计算DataTable,则可以依靠ListChanged事件。

作为另一种选择,您可以依靠Sum的{​​{1}},ListChangedRowsAdded事件来计算RowsRemoved

示例-数据表-列的总和

CellValueChanged引发DataGridView事件。您可以订阅事件以更新文本框:

Sum

示例-列表-属性总和

DataTable未引发ListChange事件。您可以使用private async void Form1_Load(object sender, EventArgs e) { // Define data table var dt = new DataTable(); dt.Columns.Add("Name"); dt.Columns.Add("Price", typeof(int)); // Fill data dt.Rows.Add("Product 1", 100); dt.Rows.Add("Product 2", 200); // Set data source of data grid view this.dataGridView1.DataSource = dt; // Automatically update text box, by SUM of price textBox1.Text = $"{dt.Compute("SUM(Price)", ""):F2}"; dt.DefaultView.ListChanged += (obj, args) => textBox1.Text = $"{dt.Compute("SUM(Price)", ""):F2}"; } 作为数据源并代替处理List<T>的{​​{1}}事件:

ListChanged

答案 1 :(得分:0)

昨天我解决了滚动时滞后DataGridView的问题。 DoubleBuffered中的DataGridView具有属性.NET,但是由于某些未知的原因,它被隐藏了。 您可以通过ReflexionDataGridView编写扩展方法来启用它。

public static class ExtensionMethods
{
    public static void DoubleBuffered(this DataGridView dgv, bool setting)
    {
        Type dgvType = dgv.GetType();
        PropertyInfo pi = dgvType.GetProperty("DoubleBuffered",
            BindingFlags.Instance | BindingFlags.NonPublic);
        pi.SetValue(dgv, setting, null);
    }
}

将此代码放在项目中的某个位置,并在初始化窗体后,将属性DoubleBuffered设置为true

dataGridView1.DoubleBuffered(true);

它为我带来了DataGridView的出色表现。希望能为您提供帮助。