使用DataTable将数据加载到DataGridView的Progressbar
我有一个DataGridView
,我在其中从SQL服务器数据库加载数据。 当我加载数据时需要很长时间。
我想向用户提供数据正在加载的信息。 我可以问你在将数据加载到DataGridView
时连接Progressbar
的最佳方法是什么?
我不希望任何人为我制作完整的代码。 我只是想知道如何做到这一点。
我看到有人以赏金授予我的问题。 我想说,目前我使用这个代码,如果它适合的话我会评价。
DTGdataTable = new DataTable(); SqlDataAdapter SDA = new SqlDataAdapter SDA.Fill(DTGdataTable); dataGridView1.DataSource = DTGdataTable ;
谢谢大家的时间。
如果问题是从数据库中获取数据需要很长时间,我有一个可能的解决方案:
private void buttonLoad_Click(object sender, EventArgs e) { progressBar.Visible = true; progressBar.Style = ProgressBarStyle.Marquee; System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(loadTable)); thread.Start(); } private void loadTable() { // Load your Table... DataTable table = new DataTable(); SqlDataAdapter SDA = new SqlDataAdapter(); SDA.Fill(table); setDataSource(table); } internal delegate void SetDataSourceDelegate(DataTable table); private void setDataSource(DataTable table) { // Invoke method if required: if (this.InvokeRequired) { this.Invoke(new SetDataSourceDelegate(setDataSource), table); } else { dataGridView.DataSource = table; progressBar.Visible = false; } }
将加载数据的方法放入另一个线程,并在数据源完成时设置数据源。 应该有一个调用。 如果要在进度条中显示百分比值,请不要使用“Marquee”样式并添加另一个函数和委托,您可以调用该函数来设置进度条的值。
如果将数据绑定到网格是问题,那么您不能将绑定放入另一个线程,并且您可能会显示在另一个线程中运行的进度弹出窗口。
我希望这有帮助。
试试这个…这应该是最快的路线……
1) Add a button control. 2) Add a datagridview control. 3) Add a single column into the datagridview control. 4) Add a progressbar control. 5) Leave them all with default names.
在button1_Click事件下,添加这段代码……
int maxnumber = 1000; progressBar1.Value = 0; progressBar1.Maximum = maxnumber; for (int x = 0; x <= maxnumber - 1; x++) { Application.DoEvents(); dataGridView1.Rows.Add(new string[] {Convert.ToString(x)}); progressBar1.Value += 1; label1.Text = progressBar1.Value.ToString(); }
而已。 编辑以满足您的需求。 这不是您想要的完整确切代码,但它应该让您入门。 我冒昧宣布maxnumber保持进度条的限制。 在您的情况下,这应该是您的数据库的行数,它减去1,因为索引始终从零开始:)
上面的方法是单线程的,这意味着当你的循环还没有完成时你仍然无法进行多任务处理。 在某些情况下,根据代码的算法,使用单线程方法可能比使用multithreading路由更快。 无论如何,第二种方法是使用背景工作者。 这是人们最常喜欢的,因为用户在列表加载时仍然可以执行操作。 有点像安装程序,你可以取消安装,即使它正在做某事。 下面的网站应该让你入门。 代码在VB.NET中,但可以很容易地转换为C#:)
问题是所有数据加载在一起并从数据库返回。 您需要获取数据加载进度。 这可以从数据库完成。
-
从数据库获取数据行的计数。 (此查询将返回单个数字,因此会更快)。
-
获取部分数据(Divide&conquer strategy),您可以使用OFFSET和FETCH数据库查询。 (这是每次调用时返回的数据部分)OFFSET和FETCH在不同的数据库上可用。 在MSSQL中,它是在2012版本中引入的。
当我们从服务器获取部分数据时,我们可以计算进度。
在您的代码中,此行将占用大部分处理时间:
SDA.Fill(DTGdataTable);
所以我认为最重要的是在执行过程中跟踪进度。 要做到这一点,首先需要知道您期望的行数。 SQLDataAdapter无法提供此信息,因此您需要首先运行额外的COUNT(*)查询才能获得此数字。 然后,您可以将其用作ProgressBar上的最大值。
我的实际加载代码基于Michael Hofmeiers解决方案,但不是在Marquee模式下使用ProgressBar,而是使用Timer Control中的实际进度数据来提供它。 因此,在您的表单上,添加一个Timer控件(在我的示例中名为progressTimer),将其Interval设置为100毫秒并将Enabled设置为false。 代码然后变成:
private DataTable table = null; private void buttonLoad_Click(object sender, EventArgs e) { // TODO: Select the row count here and assign it to progressBar.Maximum progressBar.Visible = true; System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(loadTable)); thread.Start(); progressTimer.Enabled = true; } private void loadTable() { // Load your Table... this.table = new DataTable(); SqlDataAdapter SDA = new SqlDataAdapter(); SDA.Fill(table); setDataSource(table); } internal delegate void SetDataSourceDelegate(DataTable table); private void setDataSource(DataTable table) { // Invoke method if required: if (this.InvokeRequired) { this.Invoke(new SetDataSourceDelegate(setDataSource), table); } else { progressTimer.Enabled = false; dataGridView.DataSource = table; progressBar.Visible = false; } } private void progressTimer_Tick(object sender, EventArgs e) { if (this.table != null) progressBar.Value = this.table.Rows.Count; }
运行此操作时,您的应用程序将在加载过程中保持响应,并且您将看到ProgressBar更改以反映加载的行数。 仅在最后(当您在DataGridView上设置DataSource时)应用程序似乎“挂起”,但我认为没有办法避免这种情况。 您只能从主线程执行此操作,因此UI变得无法响应是不可避免的。 但在我的测试中,DataGridView可以在大约一秒钟内轻松处理300K +行,因此这不应该是一个很大的问题。
1.从谷歌下载ajax loader.gif。
2.使用此代码替换该图像..
3.相应地设定时间..
$("#ssubmit").click(function () { $("#spinner").show(); setInterval(function () { $("#spinner").hide(); }, 20000); });