c# - 使用 DataTable 作为数据源在网格中增量加载

标签 c# winforms datagridview datatable lazy-loading

在我的窗口应用程序中,有许多带有网格的屏幕。
我使用 DataTable 作为网格的数据源,DataTable 有一些非常大的数据集(> 50,000),如果我们在加载 UI 时一次加载所有数据,那么在屏幕上加载数据会花费很多时间-响应直到所有数据都没有加载,
所以我已经使用 Background Worker 在该网格中实现了增量加载。
这是代码:

// DoWork Event of the background Wroker.
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        try
        {
            while (bgstop)
            {                   
                e.Result = addNewRecord(); 
                if (Convert.ToBoolean(e.Result) == false)
                {
                    e.Cancel = true;                       
                    bgstop = false;
                    killBGWorker();
                    break;
                }
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }


    // to add/merge the records in the DataTable
    private bool addNewRecord()
    {
        int flag = 0;
        try
        {
            Thread.Sleep(500); //optional
            DataTable tableAdd = getTableData();
            if (tableAdd.Rows.Count > 0)
            {
                dtRecords.Merge(tableAdd);  // dtRecords is the DataTable which attached to grid
                flag++;
            }
            else
                backgroundWorker1.WorkerSupportsCancellation = true;
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
        if (flag > 0)
            return true;
        else
            return false;
    }


    // To get the next slot of Records from the DataBase
    private DataTable getTableData()
    {
        DataTable dt = new DataTable();
        start = nextRows * noOfRows;
        stop = start + noOfRows;
        dt = SQLHelper.getAllRecords(totalRows,noOfRows, start + 1, stop);
        nextRows++;
        return dt;
    }

    // kill the backgroudworker after the all data/records get loaded from  database to grid/DataTable 
    private void killBGWorker()
    {
        backgroundWorker1.WorkerSupportsCancellation = true;
        backgroundWorker1.CancelAsync();
    }

上面的代码获取第一个定义的记录数(比如 200),然后在后台工作人员开始并开始获取槽中的数据并将其与网格数据源合并,直到所有数据(比如 >50,000 条记录)加载到网格。
但是 UI 交互仍然存在一些问题,在数据库中的所有记录都加载到网格中之前,UI 不会挂起 2-3 秒很多次。

我经历了this但在那个例子中使用了 DataModel 但在我的例子中没有 DataModel 他们只是从 DataBase 中获取 DataTable 并且现在我们不能移动到 DataModel。

是否有任何其他方法来实现增量加载具有良好的 UI 交互?

在当前情况下是否有任何方法可以实现 IBindingList

最佳答案

您可以通过将 DataGridView 从 BindingMode 更改为 VirtualMode 来实现。 .

以下更改将尽可能多地重复使用您已有的内容,您将看到 DataGridView 以增量方式加载。我不知道您一次获取了多少记录,但您可以保持较低的数量。

将属性 VirtualMode 设置为 true。从属性 DataSource 中删除任何值。向 DataGridView 添加与 DataGrid 中的列一样多的 Unbounded 列(如果需要,这可以自动完成)。

CellValueNeeded 添加事件处理程序.

将以下代码添加到该处理程序:

private void dataGridView1_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
{
    e.Value = dtRecords.Rows[e.RowIndex][e.ColumnIndex];
}

在你的 backgroundworker1 上设置属性 WorkerReportsProgress为真
ProgressChanged 添加一个事件处理程序到您的后台工作程序.使用以下代码:

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    this.dataGridView1.RowCount = (int) e.UserState;
}

在您的方法 addNewRecord 中添加以下行:

dtRecords.Merge(tableAdd);  // dtRecords is the DataTable which attached to grid
// added to bring the number of records to the UI thread
backgroundWorker1.ReportProgress(42, dtRecords.Rows.Count);

这样,您的 datagridview 现在应该以增量方式加载其数据。技巧实际上是设置 RowCount 属性。如果它可以显示一条记录,它会向数据网格发出信号,并且它会调整其滚动条以适应相同的情况。

关于c# - 使用 DataTable 作为数据源在网格中增量加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31539684/

相关文章:

c# - 使用 jquery、ajax 和 asp.net 的评论框?

javascript - 谷歌地图javascript代码隐藏 Visual Studio

c# - 如何检测鼠标按下是否超出行调整大小区域

c# - 如何在 DataGridView 中获取选定的数据行?

c# - 从 DataGridView 获取数据表

c# - 如何使用 ASP.NET 连接到 MSSQL Express

c# - 通过Emgucv调用opencv

C# winform,如何使轨迹条随着声音文件移动(增加其值)?

C#:如何在备忘录中添加一行?

c# - Windows 窗体、设计器和单例