Question How can i copy certain buttons, textboxes and associated code

Caroline

New member
Joined
Jun 8, 2011
Messages
2
Programming Experience
5-10
I have a grid which users enter their contact information - fname,lname then phone number.

I want to know how i can when the usr clicks a button create an extra row of input boxes


And if possible be told how to make the form scrollable, so i can have many, many input boxes present when required :)


What my form looks like --

r71215.jpg
 
clicks a button create an extra row of input boxes...how to make the form scrollable, so i can have many, many input boxes present when required

For this you can use a Panel control. To make it scrollable just set the autoscroll property to true. To add a control dynamically when you click a button or any other event, just create the controls and then add it to the controls property of the panel control. You can even add it straight into the windows forms by using Me.Controls.Add().

I think the best controls to use for this would be either the Panel or FlowLayoutPanel. When the button or some event fires just create a new control like such

    Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim newButton As New Button With {.Location = New Point(0, 20), .Text = "SomeButton"}
        'be sure to set the location of the new control
        Dim newAnotherButton As New Button With {.Location = New Point(0, 60), .Text = "Other button"}

        'you can add a handler for a event on that new control too using
        AddHandler newButton.Click, Sub() MsgBox("Something happend") 'sub using Lambda Expression
        'alt method
        AddHandler newAnotherButton.Click, AddressOf someMethod

        'instead of 'Me' you would have the panelcontrol name there if thats what your using
        Me.Controls.Add(newButton)
        Me.Controls.Add(newAnotherButton)
    End Sub

    Sub someMethod(ByVal sender As Object, ByVal e As EventArgs)
        MsgBox("Something else..")
    End Sub


Create the controls and add them to the panel, flowlayout, form or whatever. Use a loop if you need to create more than one. Be sure to change the location of the new control so that it is not over or ontop of the previous control.




And Heres some sample code. I used a table layout for each row in this example.
    'Note: pnDynamicControls is a Panel control with the autoscroll property set to true
    'This method can be called when a button is clicked or something
    Sub addTextBoxRow()
        Dim strText() As String = {"FirstName", "LastName", "PhoneNumber"}

        Dim tabRow As New TableLayoutPanel With {.RowCount = 1, .ColumnCount = strText.Length, .Height = 20, .Width = 240}

        For cols As Integer = 0 To tabRow.ColumnCount
            tabRow.ColumnStyles.Add(New ColumnStyle(SizeType.Absolute, 80.0F))
        Next

        For Each txtMsg As String In strText
            Dim txtBox As New TextBox With {.Text = txtMsg, .Size = New Size(40, 20), .Anchor = AnchorStyles.None, .Dock = DockStyle.Fill}
            tabRow.Controls.Add(txtBox)
        Next

        If pnDynamicControls.Controls.Count > 0 Then
            If pnDynamicControls.Controls.Item(pnDynamicControls.Controls.Count - 1).GetType = GetType(TableLayoutPanel) Then
                Dim previousTab As TableLayoutPanel = CType(pnDynamicControls.Controls.Item(pnDynamicControls.Controls.Count - 1), TableLayoutPanel)

                tabRow.Location = New Point(0, previousTab.Location.Y + 25)
            End If
        End If

        pnDynamicControls.Controls.Add(tabRow)
    End Sub
 
Flippedbeyond said:
I used a table layout for each row in this example.
Wouldn't it be better to add rows to a TableLayoutPanel, rather than add a TableLayoutPanel for each row?
 
Rewrote it with a class- using just one tablelayoutpanel

Wouldn't it be better to add rows to a TableLayoutPanel, rather than add a TableLayoutPanel for each row?
Yeah i agree, i didn't feel like writing code for that earlier, but heres an example using just one tablelayout which makes more more sense like you said.

I wrote a class that inherited TableLayoutPanel, of course thats not necessary, i just like it better this way. Heres the rewritten code.

Public Class Form1
    Private tabLayout As TableLayout_DynamicControls

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        tabLayout = New TableLayout_DynamicControls(3, 30)
        tabLayout.Width = pnDynamicControls.Width - 20

        pnDynamicControls.Controls.Add(tabLayout)
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim columnTexts() As String = {"FirstName", "LastName", "PhoneNumber"}
        Dim newRowControls As New List(Of Control) 'felt this was easier to use compared to a fixed array which would need a loop with element numbers

        For Each columnText As String In columnTexts
            Dim txtBox As New TextBox With {.Text = columnText}
            newRowControls.Add(txtBox)
        Next

        tabLayout.AddRow(newRowControls.ToArray())
    End Sub
End Class

''' <summary>
''' Creates a TableLayout with a set number of columns, and row height with no rows. A row of controls can be added using AddRow. 
''' Column sizes are set to percent to fit all columns evenly.
''' </summary>
Class TableLayout_DynamicControls
    Inherits TableLayoutPanel

    Property RowHeight As Integer

    Sub New(ByVal colCount As Integer, ByVal rowHeight As Integer)
        MyBase.New()
        MyBase.Height = 0

        MyBase.ColumnCount = colCount
        Me.RowHeight = rowHeight


        MyBase.ColumnStyles.Clear()
        For count As Integer = 0 To colCount
            MyBase.ColumnStyles.Add(New ColumnStyle(SizeType.Percent, CSng((1 / colCount))))
        Next
    End Sub

    Sub AddRow(ByVal ParamArray controls() As Control)
        If controls.Length = MyBase.ColumnCount Then
            MyBase.Height += RowHeight
            MyBase.RowStyles.Add(New RowStyle(SizeType.Absolute, RowHeight))

            MyBase.Controls.AddRange(controls)

            For Each Control As Control In controls
                Control.Dock = DockStyle.Fill
                MyBase.SetRow(Control, MyBase.RowCount - 1)
            Next

        Else
            Throw New NotSupportedException("There must be one control for each column. Greater or Less than is not supported.")
        End If
    End Sub
End Class
 
Last edited:
You don't need to increase RowCount, AddRange method takes care of that.
TableLayoutPanel also has AutoSize property.
 
You don't need to increase RowCount, AddRange method takes care of that.
TableLayoutPanel also has AutoSize property.

Thanks JohH, i didnt know addrange did that. i edited and removed two lines of code from the previous post.

I played with the autosize property a bit,and i think leaving that optional does the trick because if it is set to true it overrides the width that is set as well.
 
Back
Top