优化绑定到DataGridView的DataTable的更新

Wil*_*ers 9 .net c# datatable datagridview

我的应用程序中有一个表单显示一些数据.当我第一次显示Form时,我将一些数据加载到DataTable中,然后将DataTable绑定到DataGridView.我还启动了一个执行一些较慢的数据库查询的异步方法.当这些慢速查询完成时,我需要更新DataTable中的几百行,填写从较慢查询返回的值,如下所示:

foreach (DataRow row in data.Rows)
{
    SlowLoadingData slow_stuff = slow_query_results[(int)row["id"]];

    row.BeginEdit();
    row[column_one] = slow_stuff.One;
    row[column_two] = slow_stuff.Two;
    row[column_three] = slow_stuff.Three;
    row.EndEdit();
}
Run Code Online (Sandbox Code Playgroud)

这非常慢,将UI线程挂起一分钟或更长时间,大概是因为每一行都在触发重绘.

经过一些研究,我发现了一种快速的方法.首先,将DataGridView绑定到绑定到DataTable的BindingSource,而不是直接绑定到DataTable.然后,在对DataTable进行更改时执行以下操作:

binding_source.SuspendBinding();
binding_source.RaiseListChangedEvents = false;
// foreach (DataRow in Data.Rows) ... code above
binding_source.RaiseListChangedEvents = true;
binding_source.ResumeBinding();
grid.Refresh();
Run Code Online (Sandbox Code Playgroud)

但是有一个问题,这是一个很麻烦的事情:上面的代码阻止DataGridView检测添加到DataTable的新行.添加到表中的任何新行都不会出现在网格中.如果使用箭头键将当前单元格选择移出网格的底端,网格也可能抛出异常,因为底层数据源有更多行,但网格没有创建网格行来显示它们.

那么,我可以看到两种可能的解决方案:

  1. 在更改底层DataTable时是否有更好的方法来抑制绑定更新?

  2. 是否有一种简单的方法可以告诉DataGridView正常刷新其网格行集合以匹配基础DataTable行的数量?(注意:我尝试过调用BindingSource.ResetBindings,但是如果从DataTable中删除了行,它似乎会触发更多异常!)

BFr*_*ree 6

您可以尝试在DataTable上使用Merge方法.我将尝试创建一个简单的演示应用程序并在此处发布,但这个想法很简单.如果要更新网格,请将结果查询到新的DataTable,然后将旧表与新表合并.只要两个表都有主键(如果它们不从DB返回,您可以将它们创建为内存),那么它应该跟踪更改并无缝更新DataGridView.它还具有不会丢失用户在网格上的位置的优点.

好的,这是一个样本.我创建了一个带有两个按钮和一个dataGridView的表单.在按钮1上单击,我用一些数据填充主表,并将网格绑定到它.然后,在第二次单击时,我创建具有相同模式的另一个表.向其添加数据(一些具有相同的主键,一些具有新的主键).然后,他们将它们合并回原始表.它按预期更新网格.

    public partial class Form1 : Form
    {
        private DataTable mainTable;
        public Form1()
        {
            InitializeComponent();
            this.mainTable = this.CreateTestTable();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            for (int i = 1; i <= 10; i++)
            {
                this.mainTable.Rows.Add(String.Format("Person{0}", i), i * i);
            }

            this.dataGridView1.DataSource = this.mainTable;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            DataTable newTable = this.CreateTestTable();
            for (int i = 1; i <= 15; i++)
            {
                newTable.Rows.Add(String.Format("Person{0}", i), i + i);
            }
            this.mainTable.Merge(newTable);
        }

        private DataTable CreateTestTable()
        {
            var result = new DataTable();
            result.Columns.Add("Name");
            result.Columns.Add("Age", typeof(int));
            result.PrimaryKey = new DataColumn[] { result.Columns["Name"] };

            return result;

        }
    }
Run Code Online (Sandbox Code Playgroud)


Hen*_*man 4

您是否考虑过在填充表格时断开 dataGrid 或 bindingSource 并随后重新连接?它可能看起来有点难看,但应该会快很多。