我在 Winforms 应用程序中有一个 DataGridView,大约有 1000 行(未绑定)和 50 列。隐藏一列需要整整 2 秒。当我想隐藏大约一半的行时,这就成为一个问题。
private void ShowRows(string match)
{
this.SuspendLayout();
foreach (DataGridViewRow row in uxMainList.Rows)
{
if (match == row.Cells["thisColumn"].Value.ToString()))
{ row.Visible = false; }
else
{ row.Visible = true; }
}
this.ResumeLayout();
}
我通过在操作周围添加
Console.WriteLine(DateTime.Now)
来进行一些测试,而row.Visible = false
绝对是慢一点。我是否遗漏了一些明显的东西,例如设置IsReallySlow = false
?或者我是否必须继续启用虚拟模式并编写必要的事件?
在我看来你应该使用行过滤器。
尝试使用 DataView 作为绑定源,并使用 DataView.RowFilter 隐藏行或显示您选择的行。
DataGridView myGridView = new DataGridView();
DataView myDataView = myTable.DefaultView;
myGridView.DataSource = myDataView; // DataView that allows row filtering
myDataView.RowFilter = string.Format("thisColumn <> '{0}'",match); // this will hide all rows where "thisColumn" = match
在大多数情况下,属性 DataGridViewAutoSizeColumnMode 会使 DGV 变慢。 当您将所有列更改为 DataGridViewAutoSizeColumnMode.None 模式时,您的性能将显着提高。之后您可以以同样的方式将其重置为之前的状态。
For Each col As DataGridViewColumn In myDGV.Columns
col.AutoSizeMode = DataGridViewAutoSizeColumnMode.None
Next
您将看到隐藏 1000 列中的一些现在只需要 1-2 秒。对于其他属性(SuspendLayout、隐藏整个表单等)我找不到任何效果。
如上所述,是
DataGridViewAutoSizeColumnMode
扼杀了性能。不要循环遍历 DatagridView
的每一行并更改自动调整大小模式,而是对整个 Datagridview
进行此操作,首先将其关闭,然后在执行所需的行逻辑后再次打开它
YourDatagridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None
// Perform row visibility here...
YourDatagridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells
只是一个问题..是否可以将该匹配参数传递给数据库查询或过程并获取与记录不匹配的行。这样你就不必担心显示/隐藏,而且速度会更快,而且你将不再循环。 随着记录数量随着时间的推移而增加,这也将起作用..
只是一个可能不适用于您的想法..请告诉我。
要根据
AutoSizeColumnsMode
属性的重置来实现优化以加快 DataGridViewRow 中行的隐藏速度,您可以使用此类:
Public Class DataGridViewUtil
Private dgv As DataGridView
Private sizeColumnModeBackup(-1) As DataGridViewAutoSizeColumnMode
Public Sub New(dgv As DataGridView)
Me.dgv = dgv
End Sub
''' <summary>
''' Prepare datagridview before we do the row hidding to speedup it
''' </summary>
''' <remarks>We use a method based on reseting the AutoSizeColumnMode
''' property to None, therefore it will be necessary to call
''' HidingRowsSpeederAfer() when we finish hiding rows</remarks>
Public Sub HidingRowsSpeederBefore()
ReDim sizeColumnModeBackup(dgv.Columns.Count)
For Each col As DataGridViewColumn In dgv.Columns
sizeColumnModeBackup(col.Index) = col.AutoSizeMode
col.AutoSizeMode = DataGridViewAutoSizeColumnMode.None
Next
End Sub
''' <summary>
''' Restore DataGridView state changed when HidingRowsSpeederBefore()
''' was called
''' </summary>
''' <remarks>This procedure must be called after the row hidding has been
''' done and requires a previous call to HidingRowsSpeederBefore()</remarks>
Public Sub HidingRowsSpeederAfter()
If dgv Is Nothing Then
Throw New NullReferenceException("The assigned datagridview is null")
End If
If sizeColumnModeBackup.Length < dgv.Columns.Count Then
Throw New Exception("Mismatch on internal SizeColumnMode array, " &
"maybe you forgot to call HidingRowsSpeederBefore()")
End If
For Each col As DataGridViewColumn In dgv.Columns
col.AutoSizeMode = sizeColumnModeBackup(col.Index)
Next
End Sub
End Class
使用方法:
Dim dgvUtil As New DataGridViewUtil(yourDataGridView)
dgvUtil.HidingRowsSpeederBefore()
'... do your row hidding chores here
dgvUtil.HidingRowsSpeederAfter()
在隐藏行之前隐藏所有列,然后再次显示列对我来说效果很好。
dgvMain.CurrentCell = Nothing
dgvMain.SuspendLayout()
dgvMain.Visible = False
For Each col As DataGridViewColumn In dgvMain.Columns
col.Visible = False
Next
*** Hide your rows here ***
For Each col As DataGridViewColumn In dgvMain.Columns
col.Visible = True
Next
dgvMain.Visible = True
dgvMain.ResumeLayout()