unholymackerel
unholymackerel

Reputation: 89

vb.net working with multiple controls added at runtime

I am adding a tab page and datagridview to a Tab Control for every record in a datatable.

I would like to have a new Tab/DataGridView for each record (there will be ~3 for right now). I am declaring a new DataGridView D. How do I refer to these controls later?

I will want to do things like save changes in the datagridview to the database. Currently I can get the data on the screen and it looks good, but I believe I am not adding the DataGridView controls correctly because I keep re-using "D" as the control.

            Dim dt As New DataTable

        GetDataTable("SELECT * FROM aFeeTypes DescSeq", dt)

        Dim i As Integer

        'for each class in the datatable add a tab and a datagridview
        For i = 0 To dt.Rows.Count - 1

            Dim dr As DataRow
            dr = dt.Rows(i)

            Dim D = New DataGridView
            D.Visible = True

            Dim tp As New TabPage
            tp.Name = "tp" & i
            tp.Text = dr.Item("Desc2")
            frmUI.tcFee.TabPages.Add(tp)
            frmUI.tcFee.TabPages(i).Controls.Add(D)

            dgv_Fill(D, "SELECT * FROM Fee WHERE ClassID=" & dr.Item("ClassID") & " ORDER BY Seq")

            D.AutoResizeColumns()
            D.Width = tp.Width
            D.Height = tp.Height

        Next i

this does not work:

            With frmUI.Controls("D" & i)
                .AutoResizeColumns()
                .Width = tp.Width
                .Height = tp.Height
            End With

Upvotes: 1

Views: 1402

Answers (2)

unholymackerel
unholymackerel

Reputation: 89

I found a solution to the problem. The problem is that the new row has an autonumber ID.

When da.update(dt) occurs, the new row is inserted to the database. The database knows the new autonumber ID. However, the datatable does not.

For the datatable to know, the dataadapter is refilled. However, this causes the datatable to have all the old rows plus all the new rows and they all appear in the datagridview.

By clearing the old rows from the datatable, the fill refreshes all the data in the datatable and therefore refreshes the datagridview.

    Public Sub dgv_AddRow(ByVal dgvName As String)

    Dim dgv As DataGridView = colDataGridView.Item(dgvName)

    Dim da As SqlDataAdapter = colDataAdapter.Item(dgvName)
    Dim dr As DataRow = frmUI.allDataSet.Tables(dgvName).NewRow

    'autopopulate the class id
    dr("ClassID") = dgv.Parent.Tag

    'add the new row
    frmUI.allDataSet.Tables(dgvName).Rows.Add(dr)

    'get the changed table
    Dim dt As DataTable = frmUI.allDataSet.Tables(dgvName)

    'inserts the new row to the database.  concurrency violation 
    'will occur because datatable does not know the new Autonumber ID for the new row.

    da.Update(dt)

    'remove the datatable rows so they can be replaced using the adapter fill
    'if rows are not cleared, following fill causes datatable to 
    'have existing rows plus all the rows again due to the fill

    frmUI.allDataSet.Tables(dgvName).Rows.Clear()

    'refill the adapter (refill the table)
    'Everything you do to the underlying dataTable
    'gets displayed instantly on the datagridview

    da.Fill(frmUI.allDataSet, dgvName)



End Sub

Upvotes: 0

Adriaan Stander
Adriaan Stander

Reputation: 166376

D is purely the variable name in the scope you are using it in.

You need to give the control a unique Name that yo can reference it by later.

The Name property can be used at run time to evaluate the object by name rather than type and programmatic name. Because the Name property returns a String type, it can be evaluated in case-style logic statements (Select statement in Visual Basic, switch statement in Visual C# and Visual C++).

Upvotes: 1

Related Questions