在DataGridView中隐藏行非常慢

时间:2010-03-20 13:45:14

标签: c# .net winforms datagridview

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

5 个答案:

答案 0 :(得分: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

答案 1 :(得分:4)

在大多数情况下,属性DataGridViewAutoSizeColumnMode使DGV变慢。 将所有列更改为Mode DataGridViewAutoSizeColumnMode.None时,性能会急剧增加。之后,您可以按照与之前状态相同的方式重置它。

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

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

答案 2 :(得分:2)

如上所述,DataGridViewAutoSizeColumnMode杀死了表演。不是循环遍历DatagridView的每一行并更改自动调整大小模式,而是通过最初将其关闭然后在执行所需的行逻辑后再次打开它来代替整个Datagridview

YourDatagridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None

     // Perform row visibility here...

YourDatagridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells

答案 3 :(得分:0)

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

只是一个可能不适合你的想法......我知道。

答案 4 :(得分: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()