VB.NET - 更新大数据表的更快方法,它是DataGridView的DataSource吗?

时间:2017-08-08 04:28:16

标签: arrays vb.net datagridview datatable

我只使用一个2D数组,即x(,)As Object,它基于用户打开的矩形数据文件。 x(,)的内容主要是数字单精度或双精度实数和整数。因此,阵列可以具有从x(100,100)到例如x(100,100)的尺寸。 X(100000,1000)。

datagridview是动态创建的,并通过调用DGVCREATE类进行更新。

作为尝试减少datagridview使用的数据源的sizer,有一个datagridview1.scroll的AddHandler,这样当用户滚动datagridview时,左上角的单元格行和列将被删除,然后是尝试将x(,)数组中接下来的20列和接下来的50行添加到DataTable中,DataTable假定更新datagridview中显示的数据。但这不起作用。

一个问题,如果我使用用户输入的整个数组填充DataTable,如何设置datagridview1,以便只将50行和20列添加到可见范围。如果没有滚动的addhandler来挑选用户在数组中的位置,并且将整个数组填充到DataTable中,这段代码工作正常,但是在计算更新后添加列时需要很长时间来更新DataTable,这需要添加更多领域。换句话说,当有例如DataTable中有1000行和50个字段,另外20列添加到x(,)[即Redim Preserve x(行,50 + 20)],然后更新DataTable,需要很长时间才能添加额外的当DataTable已有1000行和50列时,它们有20列。

'In a global module:
Public MainDataTable As New DataTable
Public FieldType() As Byte ' Byte array to denote the type of field (object, double, long, string, etc.)


Sub showdgv()
    Dim x(1000, 100) As Object
    Dim columnheaders(100) As String
    Dim rowheaders(1000) As String
    Dim fieldnames(100) As String
    Dim rownames(1000) As String

    For i as Integer = 0 To 999
       For j As Integer = 0 to 99
           x(i, j) = Rnd()
       Next
    Next

    'Dynamically create a datagridview
    Dim datagridview1 As New DataGridView
    Me.Controls.Add(datagridview1)
    datagridview1.AutoSize = True
    datagridview1.AutoResizeRows()
    datagridview1.AutoResizeColumns()
    datagridview1.ClearSelection()
    DoubleBufferedDGV(datagridview1, True)
    datagridview1.AutoResizeRowHeadersWidth(DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders)
    Dim dgvColumnHeaderStyle As New DataGridViewCellStyle()
    dgvColumnHeaderStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
    datagridview1.ColumnHeadersDefaultCellStyle = dgvColumnHeaderStyle
    datagridview1.AllowUserToAddRows = False
    datagridview1.ScrollBars = ScrollBars.Both
    datagridview1.Refresh()
    datagridview1.Dock = DockStyle.Fill
    AddHandler datagridview1.Scroll, AddressOf Me.DGV1_Scroll

    'Instantiate the class object to update the DGV by loading the DataTable with the contant of the array x(,) 
    Dim dgv As New DGVCREATE(datagridview1, x, columnheaders, rowheaders, FieldNames, RowNames)

End Sub


Public Class DGVCREATE
    Dim x(,) As Object
    Dim columnheaders() As String
    Dim rowheaders() As String
    Dim fieldnames() As String
    Dim rownames() As String
    Sub New(ByRef dgv As DataGridView, ByVal x(,) As Object, ByVal columnheaders() As String, ByVal rowheaders() As String, ByVal FieldNames() As String, ByVal RowNames() As String)
        Dim main As Form1 = CType(Application.OpenForms(0), Form1)
        dgv.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.DisableResizing
        GetResultsTable(x, columnheaders, rowheaders, FieldNames, RowNames)
        'new trial code
        dgv.AutoGenerateColumns = True
        'Application.DoEvents()
        dgv.DataSource = main.MainDataTable
        dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
        For i As Integer = 0 To main.MainDataTable.Columns.Count - 1
            Dim Column As New DataGridViewTextBoxColumn
            Column.Name = main.MainDataTable.Columns(i).ColumnName
            Column.DataPropertyName = main.MainDataTable.Columns(i).ColumnName
            Column.HeaderText = main.MainDataTable.Columns(i).ColumnName
            Column.FillWeight = 70
            Column.MinimumWidth = 70
            dgv.Columns.Add(Column)
        Next i
        dgv.AutoSize = True
    End Sub

    Public Sub GetResultsTable(ByVal x(,) As Object, ByVal columnheaders() As String, ByVal rowheaders() As String, ByVal fieldnames() As String, ByVal rownames() As String)
        Dim main As Form1 = CType(Application.OpenForms(0), Form1)
        main.MainDataTable.Clear()
        main.MainDataTable.Rows.Clear()
        main.MainDataTable.Columns.Clear()

        ' Loop through all process names.
        For j As Integer = dgvbegincol To dgvbegincol + 30 ' 0 To UBound(columnheaders) - 1
            ' The current process name.
            ' Add the program name to our columns.
            Try
                If FieldType(j + 1) = 0 Then main.MainDataTable.Columns.Add(fieldnames(j + 1), GetType(Object))
                If FieldType(j + 1) = 1 Then main.MainDataTable.Columns.Add(fieldnames(j + 1), GetType(Double))
                If FieldType(j + 1) = 2 Then main.MainDataTable.Columns.Add(fieldnames(j + 1), GetType(Long))
                If FieldType(j + 1) = 3 Then main.MainDataTable.Columns.Add(fieldnames(j + 1), GetType(Long))
                If FieldType(j + 1) = 4 Then main.MainDataTable.Columns.Add(fieldnames(j + 1), GetType(String))
            Catch ex As Exception
                If InStr(ex.Message, "column name") > 0 Then
                    Try
                        If FieldType(j + 1) = 0 Then main.MainDataTable.Columns.Add(fieldnames(j + 1) & "_" & varsuffixvalue.ToString, GetType(Object))
                        If FieldType(j + 1) = 1 Then main.MainDataTable.Columns.Add(fieldnames(j + 1) & "_" & varsuffixvalue.ToString, GetType(Double))
                        If FieldType(j + 1) = 2 Then main.MainDataTable.Columns.Add(fieldnames(j + 1) & "_" & varsuffixvalue.ToString, GetType(Long))
                        If FieldType(j + 1) = 3 Then main.MainDataTable.Columns.Add(fieldnames(j + 1) & "_" & varsuffixvalue.ToString, GetType(Long))
                        If FieldType(j + 1) = 4 Then main.MainDataTable.Columns.Add(fieldnames(j + 1) & "_" & varsuffixvalue.ToString, GetType(String))
                        fieldnames(j + 1) = fieldnames(j + 1) & "_" & varsuffixvalue.ToString
                    Catch ex1 As Exception
                        If InStr(ex1.Message, "column name") > 0 Then
                            varsuffixvalue += 1
                            If FieldType(j + 1) = 0 Then main.MainDataTable.Columns.Add(fieldnames(j + 1) & "_" & varsuffixvalue.ToString, GetType(Object))
                            If FieldType(j + 1) = 1 Then main.MainDataTable.Columns.Add(fieldnames(j + 1) & "_" & varsuffixvalue.ToString, GetType(Double))
                            If FieldType(j + 1) = 2 Then main.MainDataTable.Columns.Add(fieldnames(j + 1) & "_" & varsuffixvalue.ToString, GetType(Long))
                            If FieldType(j + 1) = 3 Then main.MainDataTable.Columns.Add(fieldnames(j + 1) & "_" & varsuffixvalue.ToString, GetType(Long))
                            If FieldType(j + 1) = 4 Then main.MainDataTable.Columns.Add(fieldnames(j + 1) & "_" & varsuffixvalue.ToString, GetType(String))
                            fieldnames(j + 1) = fieldnames(j + 1) & "_" & varsuffixvalue.ToString
                        End If
                    End Try
                End If
            End Try

            Do While main.MainDataTable.Rows.Count < UBound(rowheaders)
                Dim myRow As DataRow
                myRow = main.MainDataTable.NewRow()
                main.MainDataTable.Rows.Add(myRow)
            Loop
            ' Add each item to the cells in the column.
            For i As Integer = dgvbeginrow To dgvbeginrow + 50 '  0 To UBound(rowheaders) - 1
                main.MainDataTable.Rows(i)(j) = If(x(i, j), CObj(DBNull.Value))
            Next i
        Next j
        dgvThreadDone.Set()
    End Sub
End Class

Sub DGV1_Scroll(sender As Object, e As ScrollEventArgs)
    Dim x(,) As Object
    Dim rowheaders() As String, columnheaders() As String
    rowheaders = RowNames.Clone
    columnheaders = FieldNames.Clone

    For Each c In Me.Controls
        If TypeOf (c) Is DataGridView Then
            'Public dgvbeginrow, dgvendrow, dgvbegincol, dgvendcol As Integer
            dgvbeginrow = c.FirstDisplayedCell.RowIndex
            dgvbegincol = c.FirstDisplayedCell.ColumnIndex

            Dim dgv As New DGVCREATE(c, x, columnheaders, rowheaders, FieldNames, RowNames)

        End If
    Next
End Sub

1 个答案:

答案 0 :(得分:1)

我认为使用DataTable填充DataGridView可以获得更好的结果:

Public Class Form1
  'For this example, add a DataGridView and Button under it 
  Sub New()

    ' This call is required by the designer.
    InitializeComponent()

    ' Add any initialization after the InitializeComponent() call.
    Dim dtb As New DataTable()
    'Start with 50 columns and 1000 rows
    For intCol As Integer = 0 To 49
      dtb.Columns.Add("Col" & intCol.ToString("000"))
    Next intCol
    For intRow As Integer = 0 To 999
      Dim drw As DataRow = dtb.NewRow
      For intCol As Integer = 0 To 49
        drw(intCol) = Rnd()
      Next intCol
      dtb.Rows.Add(drw)
    Next intRow
    DataGridView1.DataSource = dtb
    DataGridView1.Anchor = AnchorStyles.Top Or AnchorStyles.Left Or AnchorStyles.Right Or AnchorStyles.Bottom
    Button1.Anchor = AnchorStyles.Left Or AnchorStyles.Bottom
  End Sub

  Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    'Add 20 columns
    Me.Cursor = Cursors.WaitCursor
    Dim dtb As DataTable = DirectCast(DataGridView1.DataSource, DataTable)
    Dim intOldColumnCount As Integer = dtb.Columns.Count
    For intCol As Integer = intOldColumnCount To intOldColumnCount + 20
      dtb.Columns.Add("Col" & intCol.ToString("000"))
    Next intCol
    For intRow As Integer = 0 To dtb.Rows.Count - 1
      Dim drw As DataRow = dtb.Rows(intRow)
      For intCol As Integer = intOldColumnCount To intOldColumnCount + 20
        drw(intCol) = Rnd()
      Next intCol
    Next intRow
    Me.Cursor = Cursors.Default
  End Sub
End Class