Home > Net >  Creating a function that dynamically creates form controls in VB.net
Creating a function that dynamically creates form controls in VB.net

Time:08-17

I am trying to create a general function in VB.NET that can dynamically create a form object (label , button etc.) and this object can be pin the form or container . My problem is i am unable to pass the control object type to the function when calling it. Visual studio gives error.

Private Function AddnewObject(newObject As Integer, ContainerObject As Object, ByRef Objectn As Control) As System.Windows.Forms.Control`
    ContainerObject.Controls.Add(Objectn)
    Objectn.Top = 560   (newObject * 27)
    Objectn.Left = 100
    Objectn.Text = Objectn.ToString & newObject.ToString
    newObject  = 1 ' useless in this context 
    Return Objectn
End Function

when trying to call it like this :

AddnewObject(concounter, TableLayoutPanel1, Label)

i get error

BC30109 'Label' is a class type and cannot be used as an expression.

I tried to change the type of objectn but can't figure the correct one/way to use

CodePudding user response:

You can pass a type as parameter with generic type parameters (the (Of T) part in front of the normal parameter list). Normal Sub or Function parameters can be only values, not types (though they can be of type System.Type).

I suggest to change the function like this

Private conCounter As Integer = 1

Private Function AddNewControl(Of T As {Control, New})(controls As Control.ControlCollection) As T
    Dim newControl As T = New T()
    controls.Add(newControl)
    With newControl
        .Top = 560   (conCounter * 27)
        .Left = 100
        .Name = GetType(T).Name & conCounter
    End With
    conCounter  = 1
    Return newControl
End Function

and to call it like this

Dim newControl = AddNewControl(Of Label)(TableLayoutPanel1.Controls)

Explanation:

  • The type of the control to be created is passed as generic type parameter. The type constraint {Control, New} ensures that only control types are passed and that they have a default constructor (which is always the case for Controls).

  • I am using concrete types instead of Object. Use Option Strict On to create better quality code.

  • Since not all controls used as container object inherit from ContainerControl (e.g., TableLayoutPanel does not), I have chosen to pass the ControlCollection of the container object to this function instead.

  • The counter needs not to be passed as parameter if it is in the same class (or module)

This function does return the new control as function value. If this is not required, you can also turn it into a Sub instead.

Private Sub AddNewControl(Of T As {Control, New})(controls As Control.ControlCollection)
    Dim newControl As T = New T()
    controls.Add(newControl)
    With newControl
        .Top = 560   (conCounter * 27)
        .Left = 100
        .Name = GetType(T).Name & conCounter
    End With
    conCounter  = 1
End Sub

And call with

AddNewControl(Of Label)(TableLayoutPanel1.Controls)
  • Related