【发布时间】:2013-07-10 17:43:05
【问题描述】:
我的应用程序在一个窗体上有两个 DataGridView 控件。网格彼此相邻排列,两者都处于虚拟模式,并且行需要保持对齐。其中一个网格位于控件中,该控件公开 FirstDisplayedScrollingRowIndex 属性和滚动事件。
当任一网格滚动时,其他网格的 FirstDisplayedScrollingRowIndex 属性将设置为保持对齐。
DoubleBuffer 已通过以下方式设置为 true:
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 过程中有一些 case 语句,出于性能原因,这些语句已分解为小的 select 语句。
我尝试过以下代码:
dgv.SuspendLayout()
dgv.Refresh() ' have also tried dgv.PerformLayout()
dgv.ResumeLayout()
目前,以下粗略代码似乎提供了比 Refresh 或 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
【问题讨论】:
-
在升级到 VS 2012 之前这项工作有效吗?
-
另外:这里有人有类似问题:stackoverflow.com/questions/8260167/…
-
最近几周用户群才提出这个问题,因此 2012 年将至少发布 5 个版本。我们正在尝试查看是否可以将错误与一个特定的版本。同时发生了许多环境变化,包括用户购买了配备更大显示器的新 PC。当显示很多行时,这似乎是一个更大的问题。
-
您是否正在自动调整列的大小?
-
感谢安的链接。我已经尝试进行 Autosizing 更改,这改善了某些机器上的情况,但并非全部。 AutoSizeMode 设置为 NotSet,现在设置为 None。
标签: datagridview