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
. UseOption 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 theControlCollection
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)