2013-07-10 27 views
0

我有一個應用程序在窗體上有兩個DataGridView控件。網格排列在一起,都處於虛擬模式,並且行需要保持一致。其中一個網格位於控件中,該控件公開FirstDisplayedScrollingRowIndex屬性和滾動事件。我如何使虛擬模式下的.net DataGridView控件快速重繪時滾動

當其中一個網格滾動時,其他網格FirstDisplayedScrollingRowIndex屬性設置爲保持對齊。

雙緩衝已被設置爲使用真:

dataGridViewLines.GetType.InvokeMember("DoubleBuffered", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance Or System.Reflection.BindingFlags.SetProperty, Nothing, dgvStoreLines, New Object() {True}) 

該應用程序最初是寫在VS2005和已經升級在VB中vs2012,但很高興有在C#中的答案。

當其中任一控件設置其他控件FirstDisplayedScrollingRowIndex屬性時,會設置一個標誌,以確保第二個控件滾動事件不會返回到導致循環事件的容器。

第一格有大約50列,第二格有8-10。網格中通常有大約250-350行數據。

問題是,當使用鼠標滾輪滾動其中一個網格時,在第二個網格中的數據與第一個網格一致移動之前,即使滾動條保持完全一致,您也會有一點滯後。如果您用鼠標抓住滾動條向上或向下移動滾動條,則另一個網格上的滾動條將完美移動,但網格數據不會更改,直到滾動條被釋放。

如果刪除使它們保持對齊的代碼,則單獨按照預期方式滾動每個網格。

由於性能原因,CellValueNeeded過程中有些語句被細分爲小的select語句。

沿線的我曾嘗試代碼:

dgv.SuspendLayout() 
dgv.Refresh() ' have also tried dgv.PerformLayout() 
dgv.ResumeLayout() 

目前以下粗略代碼似乎提供了更好的結果比任何刷新或PerformLayout。

For i As Integer = 0 To dgv.ColumnCount - 1 
    If dgv.Columns(i).Visible AndAlso dgv.Columns(i).Displayed Then 
     dgv.InvalidateColumn(i) 
    End If 
Next 

下面的代碼重新錯誤到一定量 - 這試圖表明大多數正在設置的屬性 - 我不能發佈任何實際的代碼。創建我已經添加到datagridview控件的應用程序,並將它們錨定到表單邊緣。第二個網格添加了一個DataGridViewComboBoxColumn列 - 沒有屬性更改,六個值添加到列表A-F。

Private IsSettingDataGridView1RowIndex As Boolean = False 
Private IsSettingDataGridView2RowIndex As Boolean = False 
Private ReadOnlyColour As System.Drawing.Color = Color.FromArgb(255, 255, 255, 192) 


Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load 

    For grid1columns As Integer = 0 To 50 
     DataGridView1.Columns.Add("Column " + grid1columns.ToString, "Column " + grid1columns.ToString) 
     DataGridView1.Columns(grid1columns).AutoSizeMode = DataGridViewAutoSizeColumnMode.None 
    Next 
    For grid1columns As Integer = 0 To 10 
     DataGridView2.Columns.Add("Column " + grid1columns.ToString, "Column " + grid1columns.ToString) 
     DataGridView1.Columns(grid1columns).AutoSizeMode = DataGridViewAutoSizeColumnMode.None 
    Next 
    PrepGrid(DataGridView1) 
    PrepGrid(DataGridView2) 

End Sub 

Private Sub PrepGrid(dgv As DataGridView) 
    dgv.VirtualMode = True 
    dgv.RowCount = 300 
    dgv.AllowUserToAddRows = False 
    dgv.AllowUserToResizeRows = False 
    dgv.ColumnHeadersDefaultCellStyle.WrapMode = DataGridViewTriState.True 
    dgv.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing 
    dgv.DefaultCellStyle.WrapMode = DataGridViewTriState.False 
    dgv.EditMode = DataGridViewEditMode.EditOnKeystroke 
    dgv.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.DisableResizing 
    dgv.ShowCellToolTips = False 
    dgv.StandardTab = True 
    dgv.RowHeadersVisible = False 
    dgv.ScrollBars = ScrollBars.Vertical 
End Sub 

Private Sub DataGridView1_CellValueNeeded(sender As Object, e As DataGridViewCellValueEventArgs) Handles DataGridView1.CellValueNeeded 
    e.Value = String.Format("val r{0} c{1}", e.RowIndex, e.ColumnIndex) 
End Sub 

Private Sub DataGridView2_CellValueNeeded(sender As Object, e As DataGridViewCellValueEventArgs) Handles DataGridView2.CellValueNeeded 
    If e.ColumnIndex > 0 Then e.Value = String.Format("val r{0} c{1}", e.RowIndex, e.ColumnIndex) 
    DataGridView2.Rows(e.RowIndex).Cells(e.ColumnIndex).ReadOnly = (e.ColumnIndex < 2) 
    If e.ColumnIndex < 2 Then DataGridView2.Rows(e.RowIndex).Cells(e.ColumnIndex).Style.BackColor = ReadOnlyColour 
End Sub 

Private Sub DataGridView1_Scroll(sender As Object, e As ScrollEventArgs) Handles DataGridView1.Scroll 
    If Not IsSettingDataGridView2RowIndex Then 
     IsSettingDataGridView2RowIndex = True 
     DataGridView2.FirstDisplayedScrollingRowIndex = DataGridView1.FirstDisplayedScrollingRowIndex 
     IsSettingDataGridView2RowIndex = False 
    End If 
End Sub 

Private Sub DataGridView2_Scroll(sender As Object, e As ScrollEventArgs) Handles DataGridView2.Scroll 
    If Not IsSettingDataGridView1RowIndex Then 
     IsSettingDataGridView1RowIndex = True 
     DataGridView1.FirstDisplayedScrollingRowIndex = DataGridView2.FirstDisplayedScrollingRowIndex 
     IsSettingDataGridView1RowIndex = False 
    End If 
End Sub 
+0

在升級到VS 2012之前完成此工作嗎? –

+0

另外:這裏有人有類似的問題:http://stackoverflow.com/questions/8260167/datagridview-virtual-mode-and-lags?rq=1 –

+0

它只是在過去的幾個用戶羣提出幾周,因此2012年至少會有5個版本。我們正試圖查看是否可以將錯誤與特定版本相關聯。同時出現了許多環境變化,包括用戶使用更大的顯示器獲得新PC。當顯示很多行時,它似乎更像是一個問題。 – Matt

回答

0

一對夫婦的想法:

  1. 這將是有趣的,運行應用程序的一部分探查。你有一個包含profiler的VS版本嗎?聽起來好像每一個滾動動作都發生了很多,但我們不知道什麼 - 或者更確切地說,我們不知道的一切都是

  2. 您在CellValueNeeded過程中提到了一些複雜的聲音case聲明。假設「過程」並不意味着「存儲過程」,有沒有可能緩存一些這些值而不重新構建整個事情呢?

ETA:我不知道你的示例代碼多少代表了真正的代碼,但有一個很小,很小的性能調整,你可以做:預先確定的細胞改變,而不是在Rows做查詢和Columns每次收集:

DataGridViewCell cell = DataGridView2.Rows(e.RowIndex).Cells(e.ColumnIndex) 
cell.ReadOnly = (e.ColumnIndex < 2) 
If e.ColumnIndex < 2 Then cell.Style.BackColor = ReadOnlyColour 
+0

我有VS2012旗艦版,會試着從profiler製作一些東西。我也在嘗試創建一個基本的應用程序來複制問題。 case語句基本上確保e.Value被設置爲CellValueNeeded中的對象屬性,但其中將近50個。最初的開發人員將其分解爲更小的語句,因爲1個大型選擇情況塊表現不佳。 – Matt

+0

我試圖使用探查器,但不知道我可以上傳 – Matt

+0

你不需要上傳任何東西;我只是認爲配置文件信息可以讓你瞭解滾動條被移動後在幕後發生了什麼。例如:CellValueNeeded被稱爲十億次?其他東西是否佔用了大部分時間?您可能必須打開顯示.NET框架類的統計信息以及您自己的代碼的設置。 –

相關問題