在 DataGridView 中隐藏行非常慢

问题描述 投票:0回答:6

我在 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
?或者我是否必须继续启用虚拟模式并编写必要的事件?

c# .net winforms datagridview
6个回答
10
投票

在我看来你应该使用行过滤器。

尝试使用 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

5
投票

在大多数情况下,属性 DataGridViewAutoSizeColumnMode 会使 DGV 变慢。 当您将所有列更改为 DataGridViewAutoSizeColumnMode.None 模式时,您的性能将显着提高。之后您可以以同样的方式将其重置为之前的状态。

For Each col As DataGridViewColumn In myDGV.Columns
   col.AutoSizeMode = DataGridViewAutoSizeColumnMode.None
Next

您将看到隐藏 1000 列中的一些现在只需要 1-2 秒。对于其他属性(SuspendLayout、隐藏整个表单等)我找不到任何效果。


2
投票

如上所述,是

DataGridViewAutoSizeColumnMode
扼杀了性能。不要循环遍历
DatagridView
的每一行并更改自动调整大小模式,而是对整个
Datagridview
进行此操作,首先将其关闭,然后在执行所需的行逻辑后再次打开它

YourDatagridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None

     // Perform row visibility here...

YourDatagridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells

0
投票

只是一个问题..是否可以将该匹配参数传递给数据库查询或过程并获取与记录不匹配的行。这样你就不必担心显示/隐藏,而且速度会更快,而且你将不再循环。 随着记录数量随着时间的推移而增加,这也将起作用..

只是一个可能不适用于您的想法..请告诉我。


0
投票

要根据

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()

0
投票

在隐藏行之前隐藏所有列,然后再次显示列对我来说效果很好。

    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()
© www.soinside.com 2019 - 2024. All rights reserved.