2013-08-22 102 views
12

我有一個DataGridView,其中我從SQL服務器數據庫加載數據。當我加載數據時需要很長時間。使用DataTable將數據加載到DataGridView的進度條

我想給用戶提供數據加載的信息。請問您在將數據加載到DataGridView時連接Progressbar的最佳方式是什麼?

我不希望任何人爲我製作完整的代碼。我只想知道它是如何做到的。

我看到有人用賞金獎勵我的問題。我想說,目前Iam使用這個代碼,我會appriciate,如果它適合。

DTGdataTable = new DataTable(); 
SqlDataAdapter SDA = new SqlDataAdapter 
SDA.Fill(DTGdataTable); 
dataGridView1.DataSource = DTGdataTable ; 

謝謝大家的時間。

+0

[希望顯示動畫,而datagridview填充數據]的可能重複(http://stackoverflow.com/questions/6294374/want-to-show-animation-while-datagridview-is-filling-with-data ) – Shaharyar

+1

如果你需要的只是用戶知道它正在加載,用'this.Cursor = Cursors.Wait;''this.Cursor = Cursors.Default;' – wruckie

回答

17

如果問題是,它需要長時間從數據庫中提取數據,我有一個可能的解決方案爲您提供:

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」並添加另一個函數和可以調用的代理來設置進度條的值。

如果將數據綁定到網格是問題,那麼您不能將綁定放入另一個線程,並且可能會顯示在另一個線程中運行的進度彈出窗口。

我希望這會有所幫助。

-4

1.從google下載ajax loader.gif。

2.replace與此代碼,圖像..

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); 
    }); 
+0

包裝你的代碼。的WinForms ***。恕我直言,***'更好刪除問題***。 _NOT有用的答案._ – Kiquenet

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#:)

http://social.msdn.microsoft.com/Forums/vstudio/en-US/efd7510c-43ed-47c4-86a3-1fa350eb0d30/fill-datagridview-using-backgroundworker-progressbar?forum=vbgeneral

+3

'Application.DoEvents'? BackgroundWorker不會是更好的建議嗎? – LarsTech

+0

@LarsTech你是對的。背景工作者是更好的選擇,因爲Application.DoEvents仍然是單線程的。這就是爲什麼我說最快的路線,不管哪個更好。在我吃完早餐之後,我也可以做一個背景工作的方法:)謝謝你指出了先生:) –

+0

@ chris_techno25我很感謝你發佈了這個答案。據我所知,我可以將它連接到string [],那時我可能已經使用過了,但現在Iam使用'SqlDataAdapter'並加載到datagridview中,比如'SDA.Fill(DataTable);'您的解決方案是否也可以與DataTable - 'dataGridView1.DataSource = DataTable;' – Marek

2

問題是所有數據加載在一起並從數據庫返回。 您需要獲取數據加載進度。這可以從數據庫完成。

  1. 從數據庫中獲取數據行的計數。 (這個查詢會返回一個數字,所以它會更快)。

  2. 獲取零件數據(分割&征服策略),可以使用OFFSET和FETCH數據庫查詢。 (這是每次調用的數據的返回部分) OFFSET和FETCH可在不同的數據庫上使用。在MSSQL中,它是在2012版中引入的。

當我們從服務器獲取部分數據時,我們可以計算進度。

+0

也可以使用ROW_NUMBER()來獲得結果的部分。 –

2

在你的代碼,這條線會佔用大部分的處理時間:

SDA.Fill(DTGdataTable); 

所以,我認爲最重要的事情是保持跟蹤的進步,而這是執行。要做到這一點,您首先需要知道您期望的行數。 SQLDataAdapter無法提供此信息,因此您需要首先運行額外的COUNT(*)查詢才能獲取此數字。然後,您可以將其用作ProgressBar上的最大值。

我的實際加載代碼是基於Michael Hofmeiers的解決方案,但我沒有在選取框模式下使用ProgressBar,而是使用來自定時器控件的實際進度數據。因此,在表單中,添加一個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; 
} 

當你運行它,你的應用程序將加載過程中保持響應,你會看到進度變化,以反映裝載的行數。只有在最後(當您在DataGridView上設置DataSource時)應用程序纔會「掛起」,但我認爲沒有辦法避免這種情況。您只能從主線程執行此操作,因此無法避免UI無響應。但在我的測試中,DataGridView很容易在一秒鐘內處理300K +行,所以這應該不是什麼大問題。

相關問題