madlan
madlan

Reputation: 1397

Slow DataGridView Drawing\Rendering

I'm using a DataGridView to load data from a DataTable. This DataGridView is located on a tab (Forms.TabPage). When clicking this tab the datagrid takes a second or two to draw from the top down, regardless of wheather data is being loaded or not.

Is there anything I can do to speed up the Drawing\Rendering when clicking the Tab?

I Don't think the actual population of the DGV is causing this, as it's filled during form load so by the time the tabs click it would have loaded the few rows (20 - 30) it displays.

Using cn As New SqlConnection(connectionString)
            Using cmd As SqlCommand = cn.CreateCommand()

                cmd.CommandType = System.Data.CommandType.Text
                cmd.CommandText = _
                    " SELECT [finish_time], [file_name], [transfer_status]" & _
                    " FROM dbo.[transfer_log]"

                cmd.Notification = Nothing

                cn.Open()


                Dim columnSpec = New DataColumn()
                With columnSpec
                    .DataType = GetType(System.String)
                    .ColumnName = "ClmFinishTime"
                End With
                Datatable1.Columns.Add(columnSpec)

                Dim columnSpec2 = New DataColumn()
                With columnSpec2
                    .DataType = GetType(System.String)
                    .ColumnName = "ClmFilename"
                End With
                Datatable1.Columns.Add(columnSpec2)

                Dim columnSpec3 = New DataColumn()
                With columnSpec3
                    .DataType = GetType(System.Byte())
                    .ColumnName = "ClmStatus"
                End With
                Datatable1.Columns.Add(columnSpec3)

                Using dr As SqlDataReader = cmd.ExecuteReader()
                    While dr.Read()

                        Dim row As DataRow = Datatable1.NewRow
                        row("ClmFinishTime") = dr.Item("finish_time")
                        row("ClmFilename") = dr.Item("file_name")

                        Select Case dr.Item("transfer_status")
                            Case 0
                                row("ClmStatus") = ConvertToByte(My.Resources.accept)
                            Case 1
                                row("ClmStatus") = ConvertToByte(My.Resources.remove)
                        End Select

                        Datatable1.Rows.Add(row)

                    End While
                End Using
        End Using
                DataGridView2.AutoGenerateColumns = False
                DataGridView2.DataSource = Datatable1

Upvotes: 1

Views: 10524

Answers (4)

Phillip
Phillip

Reputation: 660

Alternatively to @madlan simply set the DoubleBuffered property in the constructor by inheriting the control.

public class DoubleBufferedDataGridView : DataGridView
{
    public DoubleBufferedDataGridView() : base()
    {
        this.DoubleBuffered = true;
    }
}

Upvotes: 1

Samskara
Samskara

Reputation: 81

My two cents on this. I had a DGV that was extremely slow, even with only 100 records. Running the query wasn't the issue -- it returned results in milliseconds.

I tried the various 'doublebuffer' techniques, to no avail.

With my DGV on a TabControl, I was thinking there was possibly an issue with TabControls + DGVs.

To troubleshoot this, I created a new form, added a DGV, and had it populate the DGV on the form load event. I was quite happy to see the data loaded instantly.

I then started going through each property I had set on my original DGV, changing only one at a time, then opening the form. The DGV loaded instantly, until I set the RowHeadersWidthSizeMode. The default setting for this is 'EnableResizing', whereas my original, slow DGV had been changed to 'AutoSizeToAllHeaders'.

enter image description here

vs.

enter image description here

Sure enough, setting this back to the default of 'EnableResizing' resolved my slow DGV issue. I'm able to reproduce this side-by-side. Leave the DGV @ 'EnableResizing', DGV loads instantly. Change it to 'AutoSizeToAllHeaders' and it takes 1-2 seconds before the DGV loads.

Just thought I'd share my experience with this.

Upvotes: 4

Rob Sherratt
Rob Sherratt

Reputation: 131

I had a similar problem due to placing the DataGridView object into a TableLayoutPanel. The default behavior in Visual Studio of a TableLayoutPanel has the following property:

Focus -> CausesValidation = True

Due to this, it was taking up to 10 minutes to populate the DataGridView from a large DataTable.

In the Forms Designer, I set this value to

Focus -> CausesValidation = False

My DataGridView now works properly, it redraws in a second or less, and its data source is linked to a DataTable containing 2,000 rows and 100 columns, some cells holding text of up to 32,767 characters. Its response to the user editing cells etc. has no apparent delay.

Upvotes: 0

madlan
madlan

Reputation: 1397

I fixed this by double buffering the control:

Public Shared Sub SetDoubleBuffered(ByVal control As Control)
    GetType(Control).InvokeMember("DoubleBuffered", BindingFlags.SetProperty Or BindingFlags.Instance Or BindingFlags.NonPublic, Nothing, control, New Object() {True})
End Sub

Upvotes: 8

Related Questions