0
votes

I am working with only one 2D array, i.e., x(,) As Object, and it is based on the rectangular datafile opened by a user. The contents of x(,) is mostly numeric single- or double-precision reals and integers. So, the array can have dimensions from x(100,100) to e.g. x(100000,1000).

The datagridview is created dynamically and is updated via a call to a DGVCREATE class.

As an attempt to decrease the sizer of the datasource used by the datagridview, there is an AddHandler for datagridview1.scroll, so that when the user scrolls the datagridview, the upper left cell row and column ar epicked off, and then an attempt is made to add the next 20 columns and next 50 rows from the x(,) array into the DataTable, which assumingly updates the data shown in the datagridview. This is not working however.

One question, If I fill the DataTable with the entire array that is input by the user, how can datagridview1 be set up so that only, say 50 rows and 20 columns are added to the visible range. Without the scrolling addhandler to pick off where the user is in the array, and when stuffing the entire array into DataTable, this code works fine, but it just takes a long time to update the DataTable when adding columns following a computational update which requires addition of more fields. In other words, when there is e.g. 1000 rows and 50 fields in the DataTable, and another 20 columns are added to x(,) [i.e., Redim Preserve x(rows,50+20)], and then DataTable is updated, it takes a long time to add the additional 20 columns to DataTable when it already has 1000 rows and 50 columns.

'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
I recommend you replace your 2D array with a DataTable.SSS

1 Answers

0
votes

I think you will get better results using a DataTable to populate your 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