我有一个DataGridView
,我在其中从SQL Server数据库加载数据。当我加载数据时需要很长时间。
我想向用户提供数据正在加载的信息。我可以问一下,当数据加载到Progressbar
时,DataGridView
连接的最佳方式是什么?
我不希望任何人为我制作完整的代码。我只是想知道如何做到这一点。
我看到有人以赏金授予我的问题。我想说,目前我使用这个代码,如果适合的话,我会批评。
DTGdataTable = new DataTable();
SqlDataAdapter SDA = new SqlDataAdapter
SDA.Fill(DTGdataTable);
dataGridView1.DataSource = DTGdataTable ;
感谢大家的时间。
答案 0 :(得分:20)
如果问题是从数据库中获取数据需要很长时间,我有一个可能的解决方案:
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 :(得分:3)
试试这......这应该是最快的路线......
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,因为索引始终从零开始:)
上面的方法是单线程的,这意味着当你的循环还没有完成时你仍然无法进行多任务处理。在某些情况下,根据代码的算法,使用单线程方法可能比进行多线程路由更快。无论如何,第二种方法是使用背景工作者。这是人们最常喜欢的,因为用户在列表加载时仍然可以执行操作。有点像安装程序,你可以取消安装,即使它正在做某事。下面的网站应该让你入门。代码在VB.NET中,但可以很容易地转换为C#:)
答案 2 :(得分:2)
问题是所有数据加载在一起并从数据库返回。 您需要获取数据加载进度。这可以从数据库中完成。
从数据库获取数据行的计数。 (此查询将返回单个数字,因此会更快)。
获取部分数据(Divide&amp; conquer strategy),您可以使用OFFSET和FETCH数据库查询。 (这是每次通话的数据返回部分) OFFSET和FETCH可用于不同的数据库。在MSSQL中,它是在2012版本中引入的。
当我们从服务器获取部分数据时,我们可以计算进度。
答案 3 :(得分:2)
在您的代码中,此行将占用大部分处理时间:
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 +行,所以这不应该是一个很大的问题。
答案 4 :(得分:-4)
1.从谷歌下载ajax loader.gif。
2.使用此代码替换该图像..
3.相应地设定时间..
<div id="spinner" style="display: none;">
<span id="ss" style="float: left; margin-left: 50% !Important; margin-top: 22% !Important;">
<img src="ajax-pink-loader.gif" alt="Loading..." />
</span>
</div>
$("#ssubmit").click(function () {
$("#spinner").show();
setInterval(function () {
$("#spinner").hide();
}, 20000);
});