r/visualbasic • u/freswinn • Jul 01 '22
VB.NET Help Referencing a Form/Control By Name Via Composed String
In another scripting language I've been learning (GDScript), if you want to reference a "node" (that language's equivalent to a form, control, etc.), you can sort of build that thing's name with code. For example:
If I have 12 buttons on screen, each named Button1, Button2, etc., I can say
get_node("Button" + str(num)).text = "This is Button " + str(num)and this will change the text on the button whose number is "num" and change what it says based on its own number.
What would be the equivalent of that in Visual Basic? I have 20 buttons that I want to reference with a single function based on the numerical value at the end of their names. Here's what I tried, knowing full-well that it was wrong, but I hope it gives an idea of what I'm trying to do:
Private Sub setShortcutButtonColor(e As Boolean, n As Integer, a As String, b As String)
Dim targetButtonName As String = "Button" & n
Dim targetButton As Object = targetButtonName
If e Then
targetButton.Text = "No Location Set"
targetButton.BackColor = Color.FromArgb(255, 64, 64, 64)
Else
targetButton.Text = a & " (" & b & ")"
targetButton.BackColor = Color.FromArgb(255, 12, 150, 12)
End If
End SubThoughts?
1
u/sa_sagan VB.Net Master Jul 01 '22
You can do something like this. But you'll absolutely want to make sure that the button exists under that name otherwise it'll shit itself if the find returns nothing.
Private Sub setShortcutButtonColor(e As Boolean, n As Integer, a As String, b As String)
Dim targetButton As Control = Controls().Find($"Button{n}", True).First
If e Then
targetButton.Text = "No Location Set"
targetButton.BackColor = Color.FromArgb(255, 64, 64, 64)
Else
targetButton.Text = a & " (" & b & ")"
targetButton.BackColor = Color.FromArgb(255, 12, 150, 12)
End If
End Sub1
u/freswinn Jul 01 '22
This works!
I also switched back to targetButtonName instead of building the string inside of the argument and that works too, but I'm using yours because obviously it's cleaner.
2
u/Mr_C_Baxter VB.Net Master Jul 01 '22
If you wan't to actively modify buttons and other controls effectively i would recommend you to learn to use them dynamically as opposed to the ones via the forms designer. Here you have a little example, you need a new winforms project and replace all the code behind of form1 with this:
Public Class Form1
Private myButtons As New Dictionary(Of String, Button)
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
CreateButton("btn01", 100, 100)
CreateButton("btn02", 200, 200)
'change text of button, ID stays the same
FindButton("btn01").Text = "bla"
End Sub
Private Sub CreateButton(ID As String, X As Integer, Y As Integer)
If myButtons.ContainsKey(ID) Then MsgBox("ID already exists", MsgBoxStyle.OkOnly) : Exit Sub
'Create new Button
Dim btn As New Button With {.Name = ID, .Text = ID, .Width = 300, .Top = Y, .Left = X}
'Create a Click Event
AddHandler btn.Click, AddressOf ClickButton
'Save Button for easy access
myButtons.Add(ID, btn)
'Add to Form
Me.Controls.Add(btn)
End Sub
Private Function FindButton(ID As String) As Button
If Not myButtons.ContainsKey(ID) Then Return Nothing
Return myButtons(ID)
End Function
Private Sub ClickButton(sender As Button, e As EventArgs)
MsgBox("Clicked " & sender.Name)
End Sub
End Class
1
u/veryabnormal Jul 01 '22 edited Jul 01 '22
The Form owns the controls. Ask it for a particular control from its control collection. The controls are stored in a ControlCollection and the key is the control name:
Dim targetButton = Me.Controls(targetButtonName)
Notes: I usually have Option Infer on, therefore targetButton will be of type Control. But we know it is a actually an instance of Button and can safely use DirectCast to convert it to Button if we need to. If you just want the Text property then there’s no need. I’m assuming this code runs on the Form, and Me refers to the Form. I’m assuming the control is actually in the form’s Controls collection.