Search code examples
vb.netshowdialogcontrol-array

Deleting controls each time ShowDialog is called


I have a form that I display exclusively with the ShowDialog method. In the Form_Shown event, I dynamically create a set of labels and text boxes based on a public variable set in the form making the call.

I understand that the form is not closed or destroyed but simply hidden between calls, and as such I added code at the top of my Form_Shown event to clear out any controls from a previous call, but the controls aren't being removed. I have tried ctrl.Dispose (as in the code below) and Me.Controls.Remove(ctrl). Neither produces an error, but the Textboxes are not removed and new ones are created over them. (For some reason,

This is the first time I've dynamically created/removed controls in .NET, so it's possible my yearning for VB6's control arrays have something to do with the error.

The form builds itself based on the calling form's public ListView variable. The calling form makes certain this variable is not nothing and that items are selected if and only if the user is editing an existing row.

Public Class frmTableEdit

Private isNew As Boolean
Private inputText() As TextBox

Private Sub FormTableEdit_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown
    For Each ctrl As Control In Me.Controls
        If TypeOf (ctrl) Is TextBox Or TypeOf (ctrl) Is Label Then
            ctrl.Dispose()
        End If
    Next
    With frmKioskData.TBLobj
        Dim fieldCount As Integer = .Columns.Count - 1
        isNew = .SelectedIndices.Count = 0

        '(code setting size of form and location of OK/Cancel buttons is here)

        ReDim inputText(fieldCount)
        For i As Integer = 0 To fieldCount
            Dim lbl As New Label, txt As New TextBox
            inputText(i) = txt
            Me.Controls.Add(lbl)
            Me.Controls.Add(txt)

            '(code setting size and and position of lbl & txt is here)

            'lbl.Tag = i    (I commented these lines out because I never used the 
            'txt.Tag = i    Tag property, but can if a solution calls for it.)

            lbl.Text = .Columns(i).Text
            If isNew Then
                txt.Text = ""
            Else
                txt.Text = .Items(.SelectedIndices(0)).SubItems(i).Text
            End If
        Next
    End With
End Sub

End Class

Solution

  • If @Plutonix's suggestion in the comment above does not quite work for you, I think it would be easiest and make more sense to dispose of the form after calling ShowDialog, and then when you need to show that form you create a new instance with a parameter that tells it what dynamic controls to load.

    So you'd have a New method in frmTableEdit that uses this parameter:

    Public Sub New(ByVal fieldCount As Integer)
            InitializeComponent()
            fieldCount = fieldCount  'Where fieldCount is a class variable
    End Sub
    

    And when you call this form from frmKioskData, you can do so like this:

    Dim newTableEdit As New frmTableEdit(Me.TBLobj.Columns.Count - 1)
    newTableEdit.ShowDialog()
    newTableEdit.Dispose()
    

    Then the code in your frmEditTable's Shown event just simply has to add the controls accordingly, without the need to remove old ones:

    ReDim inputText(fieldCount)
    For i As Integer = 0 To fieldCount
        Dim lbl As New Label, txt As New TextBox
        inputText(i) = txt
        Me.Controls.Add(lbl)
        Me.Controls.Add(txt)
    
        '(code setting size and and position of lbl & txt is here)
    
        'lbl.Tag = i    (I commented these lines out because I never used the 
        'txt.Tag = i    Tag property, but can if a solution calls for it.)
    
        lbl.Text = .Columns(i).Text
        If isNew Then
            txt.Text = ""
        Else
            txt.Text = .Items(.SelectedIndices(0)).SubItems(i).Text
        End If
    Next
    

    How you get the isNew value is up to you - you can add that as a second parameter to the form's New, or get it the same way you are now...w/e. If it were me I'd normally add that as another New parameter.