Visual Basic How to reference a dynamically created button - vb.net

My code creates 40 buttons dynamically I can change properties if the button is clicked using sender but how do I reference them when I click a different button
Public Sub loadButtons()
For i As Integer = 0 To 39
If i > 19 Then
gap = i + 10
Else
gap = i
End If
Dim B As New Button
Form1.panSeats.Controls.Add(B)
B.Height = 30
B.Width = 37
B.Left = ((i Mod 10) * 47) + 322
B.Top = ((gap \ 10) * 31) + 114
B.Text = Chr((i \ 10) + Asc("A")) & i Mod 10 + 1
B.Tag = i
Buttons.Add(B.Text, B)
If isBooked(i) = True Then
B.BackColor = Color.Red
Else
B.BackColor = Color.Orange
End If
AddHandler B.Click, AddressOf Form1.Button_Click
Next
End Sub
I want to be able to change the backcolor B isn't declared have tried using the button.tag but not working
Private Sub btnTestCancel_Click(sender As Object, e As EventArgs) Handles btnTestCancel.Click
B.BackColor = Color.Orange
End Sub

The Addhandler statement wires the events for all dynamically added buttons. The sender object is the one being clicked, we just need to unbox it.
AddHandler B.Click, AddressOf btns_Click
Private Sub btns_Click(sender As Object, e As EventArgs) 'no handles clause needed
Dim btn As Button = DirectCast(sender, Button)
btn.BackColor = Color.Orange
End Sub

Related

Finding the name of labels based on text inside its name

I’m not really sure this is possible but it would be helpful: I have quite a large grid of labels and would like to change the visibility of them based on words inside their names, for example finding a list of labels which all contain “Twentytwo” in their name and setting their visibility to false
Here is a solution based on Control.GetNextControl:
Const textToSearch = "Twentytwo" 'Text to search
Dim c As Control = Me.GetNextControl(Me, True)
Do Until c Is Nothing
'Check if c is label and its name contains "textToSearch"
If TypeOf c Is Label AndAlso c.Name.Contains(textToSearch) Then
c.Visible = False 'Hide this label
End If
c = Me.GetNextControl(c, True)
Loop
If you want to search "Twentytwo" in the label text and not in its name, replace c.Name.Containswith c.Text.Contains.
Let's say that your labels are all in one container, perhaps a Panel.
Further, let's assume you that you want only the specified labels to have .Visible = False, so the visibility is simply whether or not the label's name contains the given string.
You can select for controls of a particular type, so that there's no need to check the type of the control before using it, like this:
Sub SetLabelVisibility(container As Control, namePart As String)
container.SuspendLayout()
For Each lbl In container.Controls.OfType(Of Label)
lbl.Visible = lbl.Name.Contains(namePart)
Next
container.ResumeLayout()
End Sub
And you would call it with
SetLabelVisibility(Panel1, "Twentytwo")
Suspending the layout of the container while the updates to its child controls are being made is so that the display of it is done in one go.
Demonstration using an appropriately-sized Panel on a Form:
Public Class Form1
Dim tim As New Timer With {.Interval = 1000}
Sub CreateLabels(target As Panel)
For j = 0 To 6
For i = 0 To 4
Dim lbl = New Label With {
.Name = $"Label{j}_{i}",
.BackColor = Color.BlanchedAlmond,
.Text = i & j,
.Location = New Point(j * 40, i * 20),
.Size = New Size(38, 18),
.TextAlign = ContentAlignment.MiddleCenter
}
target.Controls.Add(lbl)
Next
Next
End Sub
Sub SetLabelVisibility(container As Control, namePart As String)
container.SuspendLayout()
For Each lbl In container.Controls.OfType(Of Label)
lbl.Visible = lbl.Name.Contains(namePart)
Next
container.ResumeLayout()
End Sub
Sub ChangeVisibleLabels(sender As Object, e As EventArgs)
Static n As Integer = 0
SetLabelVisibility(Panel1, n.ToString())
n = (n + 1) Mod 7
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
CreateLabels(Panel1)
AddHandler tim.Tick, AddressOf ChangeVisibleLabels
tim.Start()
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
If tim IsNot Nothing Then
RemoveHandler tim.Tick, AddressOf ChangeVisibleLabels
tim.Dispose()
End If
End Sub
End Class
Public Class Form1
Dim tim As New Timer With {.Interval = 1000}
Sub CreateLabels(target As Panel)
For j = 0 To 6
For i = 0 To 4
Dim lbl = New Label With {
.Name = $"Label{j}_{i}",
.BackColor = Color.BlanchedAlmond,
.Text = i & j,
.Location = New Point(j * 40, i * 20),
.Size = New Size(38, 18),
.TextAlign = ContentAlignment.MiddleCenter
}
target.Controls.Add(lbl)
Next
Next
End Sub
Sub SetLabelVisibility(container As Control, namePart As String)
container.SuspendLayout()
For Each lbl In container.Controls.OfType(Of Label)
lbl.Visible = lbl.Name.Contains(namePart)
Next
container.ResumeLayout()
End Sub
Sub ChangeVisibleLabels(sender As Object, e As EventArgs)
Static n As Integer = 0
SetLabelVisibility(Panel1, n.ToString())
n = (n + 1) Mod 7
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
CreateLabels(Panel1)
AddHandler tim.Tick, AddressOf ChangeVisibleLabels
tim.Start()
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
If tim IsNot Nothing Then
RemoveHandler tim.Tick, AddressOf ChangeVisibleLabels
tim.Dispose()
End If
End Sub
End Class
Public Class Form1
Dim tim As New Timer With {.Interval = 1000}
Sub CreateLabels(target As Panel)
For j = 0 To 6
For i = 0 To 4
Dim lbl = New Label With {
.Name = $"Label{j}_{i}",
.BackColor = Color.BlanchedAlmond,
.Text = i & j,
.Location = New Point(j * 40, i * 20),
.Size = New Size(38, 18),
.TextAlign = ContentAlignment.MiddleCenter
}
target.Controls.Add(lbl)
Next
Next
End Sub
Sub SetLabelVisibility(container As Control, namePart As String)
container.SuspendLayout()
For Each lbl In container.Controls.OfType(Of Label)
lbl.Visible = lbl.Name.Contains(namePart)
Next
container.ResumeLayout()
End Sub
Sub ChangeVisibleLabels(sender As Object, e As EventArgs)
Static n As Integer = 0
SetLabelVisibility(Panel1, n.ToString())
n = (n + 1) Mod 7
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
CreateLabels(Panel1)
AddHandler tim.Tick, AddressOf ChangeVisibleLabels
tim.Start()
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
If tim IsNot Nothing Then
RemoveHandler tim.Tick, AddressOf ChangeVisibleLabels
tim.Dispose()
End If
End Sub
End Class

Which auto generated picturebox was clicked? VB.net

I have the following code. Im trying to find out which of the 64 pictureboxes was clicked:
For i As Integer = 1 To 8
For j As Integer = 1 To 8
SpilleBræt(i, j) = New PictureBox 'Opretter picturebox
If (i + j) Mod 2 = 1 Then
Me.SpilleBræt(i, j).BackgroundImage = Skak.My.Resources.DarkTile
Else
Me.SpilleBræt(i, j).BackgroundImage = Skak.My.Resources.LightTile
End If
'Placering, størrelse, m.v.
Me.SpilleBræt(i, j).Location = New System.Drawing.Point((i - 1) * 103, (j - 1) * 103)
Me.SpilleBræt(i, j).Size = New System.Drawing.Size(100, 100)
Me.SpilleBræt(i, j).Name = "SpilleBrik" & i & j
Me.PanelSpilleBræt.Controls.Add(Me.SpilleBræt(i, j))
Next j
Next i
Thanks.
In order to handle a click event, the first thing you'll need is a click handler. Could be something as simple as this:
Private Sub PictureBox_Click(ByVal sender As Object, ByVal e As EventArgs)
' Do something in here
End Sub
When you create your PictureBox controls, bind the handler to their click event:
AddHandler Me.SpilleBræt(i, j).Click, AddressOf PictureBox_Click
Me.PanelSpilleBræt.Controls.Add(Me.SpilleBræt(i, j))
What this should do is invoke the PictureBox_Click method any time the user clicks on the PictureBox. Within that method, sender is the element which was clicked:
Private Sub PictureBox_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim clickedBox As PictureBox
clickedBox = CType(sender, PictureBox)
' clickedBox is the element which was clicked
End Sub

Refresh a panel when some controls deleted programmaticaly

I am using this part of code to add a Label, a TextBox a Button and a RadioButton into a Panel:
Private Sub AppsAdd_Button_Click(sender As Object, e As EventArgs) Handles AppsAdd_Button.Click
Dim lbl As New Label()
Dim count As Integer = Apps_Panel.Controls.OfType(Of Label)().ToList().Count
lbl.Name = "AppLabel_" & (count + 1)
lbl.Text = "Application #" & (count + 1) & ":"
lbl.Location = New Point(0, 28 * count)
lbl.AutoSize = False
lbl.Size = New Size(114, 21)
lbl.TextAlign = ContentAlignment.MiddleRight
lbl.Tag = count + 1
Apps_Panel.Controls.Add(lbl)
Dim txtbox As New TextBox()
count = Apps_Panel.Controls.OfType(Of TextBox)().ToList().Count
txtbox.Name = "AppTextbox_" & (count + 1)
txtbox.Text = "..."
txtbox.Location = New Point(120, 28 * count)
txtbox.Size = New Size(387, 21)
txtbox.Tag = count + 1
AddHandler txtbox.TextChanged, AddressOf TextBox_Changed
Apps_Panel.Controls.Add(txtbox)
Dim btn As New Button()
count = Apps_Panel.Controls.OfType(Of Button)().ToList().Count
btn.Name = "AppBrowseButton_" & (count + 1)
btn.Text = "Browse"
btn.Location = New Point(513, 28 * count)
btn.Size = New Size(75, 21)
btn.Tag = count + 1
AddHandler btn.Click, AddressOf Button_Click
Apps_Panel.Controls.Add(btn)
Dim radiobtn As New RadioButton()
count = Apps_Panel.Controls.OfType(Of RadioButton)().ToList().Count
radiobtn.Name = "AppRadio_" & (count + 1)
radiobtn.Text = ""
radiobtn.Location = New Point(590, 28 * count)
radiobtn.Size = New Size(14, 21)
radiobtn.Tag = count + 1
AddHandler radiobtn.Click, AddressOf RadioButton_Click
Apps_Panel.Controls.Add(radiobtn)
End Sub
Private Sub TextBox_Changed(sender As Object, e As EventArgs)
Dim textbox As TextBox = TryCast(sender, TextBox)
End Sub
Private Sub Button_Click(sender As Object, e As EventArgs)
Dim button As Button = TryCast(sender, Button)
End Sub
Private Sub RadioButton_Click(sender As Object, e As EventArgs)
Dim RadioButton As RadioButton = TryCast(sender, RadioButton)
AppToDel_Label.Text = RadioButton.Tag
End Sub
Then I use this to remove selected controls:
Private Sub AppsDel_Button_Click(sender As System.Object, e As System.EventArgs) Handles AppsDel_Button.Click
Dim Ctrl As Control
For controlIndex As Integer = Apps_Panel.Controls.Count - 1 To 0 Step -1
Ctrl = Apps_Panel.Controls(controlIndex)
If Ctrl.Name Like "*" & AppToDel_Label.Text Then
RemoveHandler Ctrl.TextChanged, AddressOf TextBox_Changed
RemoveHandler Ctrl.Click, AddressOf Button_Click
RemoveHandler Ctrl.Click, AddressOf RadioButton_Click
Apps_Panel.Controls.Remove(Ctrl)
Ctrl.Dispose()
End If
Next
End Sub
When selected controls are in the bottom of panel, panel is getting smaller in height when I delete them. But if I choose to delete from the top or the middle of panel "list", leaves an empty space and panel don't shrink! Any idea? There is anyway to refresh the panel so it can fill in the empty space?
Here is a video example.
Use a FlowLayoutPanel instead. The FlowLayoutPanel layouts the controls added to it automatically. It can arrange items horizontally or vertically.
You don't specify a location when adding them, instead you work with Margins and Paddings.
I also would combine all controls of one row (Label, TextBox, Button and RadioButton) into a UserControl. This allows you to design the rows visually instead of programmatically.
Walkthrough: Arranging Controls on Windows Forms Using a FlowLayoutPanel.
Working with Windows Forms FlowLayoutPanel (C# Corner).

How do I add buttons with event handlers to a form dynamically?

Is it possible to do this dynamically? How?
Code:
Public Class Form1
Dim c(40) As Integer
Dim IMG As PictureBox
Dim lbl_n(40) As Label
Dim lbl_pr(40) As Label
Dim lbl_ref(40) As Label
Dim lbl_dim(40) As Label
Dim lbl_col(40) As Label
Dim btn_add(40) As Button
Dim btn_rmv(40) As Button
Dim tb_qt(40) As TextBox
AddHandler btn_add(0).Click, AddressOf btn_add0_Click
AddHandler btn_add(1).Click, AddressOf btn_add1_Click
[...]
AddHandler btn_add(40).Click, AddressOf btn_add40_Click
Public Sub btn_add0_Click(ByVal sender As Object, ByVal e As System.EventArgs)
c(0) = c(0) + 1
tb_qt(0).Text = c(0)
End Sub
Public Sub btn_add1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
c(1) = c(1) + 1
tb_qt(1).Text = c(1)
End Sub
[...]
Public Sub btn_add40_Click(ByVal sender As Object, ByVal e As System.EventArgs)
c(40) = c(40) + 1
tb_qt(40).Text = c(40)
End Sub
These are the images with program running (they are edited):
Form1
Form2
I want to dynamically, because I could use more than 40 products! And I need to do 40 addhandlers, so that more 40 to remove!
How can I do that?
Yes, You can do that dynamically.
In this example, I put those buttons and textboxes into Panel.
There is example with comments which line is for what :
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'dynamically adding buttons (so You don't need create every button separately)
For x = 1 To 40
Dim btn As New Button 'create new button
btn.Name = "btn_add" & x.ToString 'set ID for button (example: btn_add1, btn_add2, ... btn_add40)
btn.Text = "+" 'set button text
btn.Tag = x.ToString 'set button NO. for finding corrent textbox whos belong to this button (for example: tb_qt1 belong to buttons btn_add1 and btn_rem1)
btn.Width = 24 'this is for styling
btn.Top = (x * btn.Height) + 3 'for styling, too. Top poistion of button
btn.Left = 0 'for styling, too. Left position of button
AddHandler btn.Click, AddressOf btnAdd_Click 'creating sub called btnAdd_Click (this sub will handle all, in this case 40, buttons)
Panel1.Controls.Add(btn) 'for this example I put buttons and textboxes into panel (autoscroll set to True)
btn = New Button 'same thing just for remove button
btn.Name = "btn_rem" & x.ToString
btn.Text = "-"
btn.Tag = x.ToString
btn.Width = 24
btn.Top = (x * btn.Height) + 3
btn.Left = btn.Width + 3
AddHandler btn.Click, AddressOf btnRem_Click 'creating sub called btnRem_Click (this sub will handle all, in this case 40, buttons)
Panel1.Controls.Add(btn)
Dim txt As New TextBox 'same thing for textboxes
txt.Name = "tb_qt" & x.ToString
txt.Text = "0"
txt.Tag = x.ToString
txt.Top = (x * btn.Height) + 3
txt.Left = btn.Left + btn.Width + 3
txt.TextAlign = HorizontalAlignment.Right
Panel1.Controls.Add(txt)
Next
End Sub
Public Sub btnAdd_Click(sender As Object, e As EventArgs)
Dim btn As Button = DirectCast(sender, Button) 'detect which button clicked. You can add line: MsgBox(btn.Name) to see what happening
Dim txt As TextBox = Panel1.Controls.Find("tb_qt" & btn.Tag.ToString, True)(0) 'find textbox which belong to this button. this is why set .Tag into buttons
txt.Text = CInt(txt.Text) + 1 'just do math and change value, by adding one(1), in textbox (by this way I avoid using Your Dim c(40) As Integer)
End Sub
Public Sub btnRem_Click(sender As Object, e As EventArgs)
Dim btn As Button = DirectCast(sender, Button) 'same thing like for btnAdd_Click, but we doing subtract for one(1) value in textbox
Dim txt As TextBox = Panel1.Controls.Find("tb_qt" & btn.Tag.ToString, True)(0)
txt.Text = CInt(txt.Text) - 1
End Sub
Because I use panel like container for all those buttons and textboxes, You have to set AutoScroll=True for panel.
I hope so You will understand how it's work for start.

How to call a dynamically created label from its associated dynamically created button's click in vb.net

I have a tab in a form. On form load, I am getting text from a text file line by line and displaying them as labels on a form Tabcontrol Tabpage along with dynamically displaying buttons beside them. Now on those buttons click I want to copy the text in the associated labels. Can anyone suggest what to put in the Nextbtn_Click event?
Dim FILE_NAME As String = "D:\1.txt"
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim i As Integer = 1
For Each line As String In System.IO.File.ReadAllLines(FILE_NAME)
Dim NextLabel As New Label
Dim Nextbtn As New Button
NextLabel.Text = line
Nextbtn.Text = "Copy"
NextLabel.Height = 22
Nextbtn.Width = 55
Nextbtn.Height = 22
NextLabel.BackColor = Color.Yellow
TabPage2.Controls.Add(NextLabel)
TabPage2.Controls.Add(Nextbtn)
NextLabel.Location = New Point(10, 10 * i + ((i - 1) * NextLabel.Height))
Nextbtn.Location = New Point(120, 10 * i + ((i - 1) * Nextbtn.Height))
AddHandler Nextbtn.Click, AddressOf Me.Nextbtn_Click
i += 1
Next
End Sub
Private Sub Nextbtn_Click(sender As Object, e As EventArgs)
End Sub
Store the assc. label in the tag property and you can cast it back when you click on the button. The sender object is the button that is currently clicked.
Dim FILE_NAME As String = "D:\1.txt"
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim i As Integer = 1
For Each line As String In System.IO.File.ReadAllLines(FILE_NAME)
Dim NextLabel As New Label
Dim Nextbtn As New Button
Nextbtn.Tag = NextLabel
NextLabel.Text = line
Nextbtn.Text = "Copy"
NextLabel.Height = 22
Nextbtn.Width = 55
Nextbtn.Height = 22
NextLabel.BackColor = Color.Yellow
TabPage2.Controls.Add(NextLabel)
TabPage2.Controls.Add(Nextbtn)
NextLabel.Location = New Point(10, 10 * i + ((i - 1) * NextLabel.Height))
Nextbtn.Location = New Point(120, 10 * i + ((i - 1) * Nextbtn.Height))
AddHandler Nextbtn.Click, AddressOf Me.Nextbtn_Click
i += 1
Next
End Sub
Private Sub Nextbtn_Click(sender As Object, e As EventArgs)
Dim s As String = DirectCast(DirectCast(sender, Button).Tag, Label).Text
End Sub
Private Sub Clicked(ByVal sender As Object, ByVal e As EventArgs)
Dim b As Button = DirectCast(sender, Button)
TextBox2.Text = b.Name
Clipboard.SetText(b.Name)
End Sub