How do I add buttons with event handlers to a form dynamically? - vb.net

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.

Related

VB.NET get control name from button created at run time

I have this code to create 3 buttons at run time, which seems to be working ok.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim rawData As String
Dim FILE_NAME As String = "C:\temp\test.txt"
Dim data() As String
Dim objReader As New System.IO.StreamReader(FILE_NAME)
Do While objReader.Peek() <> -1
rawData = objReader.ReadLine() ' & vbNewLine
data = Split(rawData, ",")
'data 0 = X loc, data 1 = Y loc, data 2 = Part Num, data 3 = Reference Des
Dim dynamicButton As New Button
dynamicButton.Location = New Point(data(0), data(1))
dynamicButton.Height = 20
dynamicButton.Width = 20
dynamicButton.FlatStyle = FlatStyle.Flat
dynamicButton.BackColor = Color.Transparent
dynamicButton.ForeColor = Color.FromArgb(10, Color.Transparent)
'dynamicButton.Text = "+"
dynamicButton.Name = data(2)
dynamicButton.FlatAppearance.BorderColor = Color.White
'dynamicButton.Font = New Font("Georgia", 6)
AddHandler dynamicButton.Click, AddressOf DynamicButton_Click
Controls.Add(dynamicButton)
Dim myToolTipText = data(3)
ToolTip1.SetToolTip(dynamicButton, myToolTipText)
Loop
End Sub
I want to get the control name that was created when I click a button, but I cannot seem to get what I need. I have been doing this on the dynamicButton_click event.
Private Sub DynamicButton_Click(ByVal sender As Object, ByVal e As System.EventArgs)
For Each cntrl In Me.Controls
If TypeOf cntrl Is Button Then
MsgBox("")
Exit Sub
End If
Next
End Sub
All you need to do is cast the sender variable to button. It will tell you which control was the source of the event:
Private Sub DynamicButton_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Dim btn As Button = DirectCast(sender, Button)
MessageBox.Show("You clicked: " & btn.Name)
End Sub
You attached an event handler to the dynamic button and that is hitting?
Couple ways you can do this:
This will give you the button you just clicked without needing to loop, the sender is the button. You need to cast it from the object to button:
MessageBox.Show(DirectCast(sender, Button).Name)
Otherwise, inside your loop, cast cntrl (the generic Control object) to the specific Button control object and then get the name.
Dim btn as Button = DirectCast(cntrl, Button)
MessageBox.Show(btn.Name)

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

Dynamic TableLayout and Control

created dynamic table layout and add some controls in to that table layout.my code
Protected Overrides Sub OnLoad(e As EventArgs)
MyBase.OnLoad(e)
dynamicTable.ColumnCount = 5
dynamicTable.RowCount = 1
For i = 1 To 5
Dim button= New button()
button.Text = i.ToString()
dynamicTable.SetColumn(button, i)
dynamicTable.Controls.Add(button)
Next
Next
End Sub
Now i added 5 buttons to the table layout.
Now i am going to click on the button. How can i know ,on which button i clicked ?
Try like this
Dim dynamicTable As New TableLayoutPanel
dynamicTable.ColumnCount = 5
dynamicTable.RowCount = 1
For i = 1 To 5
Dim button = New Button()
button.Name = "button" & i
AddHandler button.Click, AddressOf Click1
Button.Text = i.ToString()
dynamicTable.SetColumn(button, i)
dynamicTable.Controls.Add(button)
Next
Me.Controls.Add(dynamicTable)
Private Sub Click1(ByVal sender As System.Object, ByVal e As System.EventArgs)
If sender.Name = "button1" Then
MsgBox("Hi")
End If
End Sub

Computer Click Event Visual Basic

How do I create a random click event driven by the computer? Where the user doesn't get to choose where it clicks?
I have created a table that is 5 buttons wide and 5 buttons tall, and created a click event where the user clicks on a button and the random number value is added onto their score.
Dim RandomNumbers = Enumerable.Range(0, 100).ToList()
Dim RandomNumber As New Random()
For Me.TableColunm = 0 To 4 Step 1
For Me.TableRow = 0 To 4 Step 1
Dim TemporaryNumber = RandomNumbers(RandomNumber.Next(0, RandomNumbers.Count))
RandomNumbers.Remove(CInt(TemporaryNumber))
TableButtons = New Button()
With TableButtons
.Name = "TextBox" & TableColunm.ToString & TableRow.ToString
.Text = TemporaryNumber.ToString
.Width = CInt(Me.Width / 4)
.Left = CInt(TableColunm * (Me.Width / 4))
.Top = TableRow * .Height
'.Tag = TemporaryNumber
AddHandler TableButtons.Click, AddressOf UserTableButtonClickEvent
End With
GameScreen.Controls.Add(TableButtons)
Next TableRow
Next TableColunm
Catch ex As Exception
MsgBox(ex.StackTrace & vbCrLf & "index1= " & TableColunm & vbCrLf & "index2= " & TableRow)
End Try
Private Sub UserTableButtonClickEvent(sender As Object, e As EventArgs)
CType(sender, Button).BackColor = Color.LightSteelBlue
OverAllScoreInteger += CInt(CType(sender, Button).Tag)
GameScreen.UserScoreBox.Text = OverAllScoreInteger.ToString
Dim TableButton As Button = CType(sender, Button)
TableButton.Text = "#"
TableButton.Enabled = False
End Sub
How do I make another event like this but at random?
Enumerate all controls in the GameScreen.Controls collection and add them to a temporary list if they are a button. Then generate a random number in the range of the length of the list and click the button with this index:
Dim TempButtonList As New List(Of Button)
For Each c as Control in GameScreen.Controls
If TypeOf(c) Is Button Then TempButtonList.Add(CType(c, Button))
Next
Dim Rnd as New Random
TempButtonList(rnd.Next(0, TempButtonList.Count-1)).PerformClick()
The PerformClick() method does exactly the same as if you would click that button with your mouse. The If in the loop makes sure you only add buttons in the controls collection, because there may of course be other controls inside.
Complete example
It's probably easier that way (Add a FlowLayoutPanel with Size=275; 275 and two Labels to a Form):
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim Rnd As New Random
For i = 1 To 25
Dim b As New Button With {.Text = Rnd.Next(0, 100)}
b.Width = 40
b.Height = 40
FlowLayoutPanel1.Controls.Add(b)
AddHandler b.Click, AddressOf b_hndl
Next
End Sub
Private MyScore As Integer = 0
Private HisScore As Integer = 0
Dim Zug As Boolean = True
Private Sub b_hndl(sender As Object, e As EventArgs)
Dim ThisB As Button = CType(sender, Button)
Dim CurrScore As Integer = CInt(ThisB.Text)
Dim CurrZug As Boolean = Zug
Zug = Not Zug
ThisB.Enabled = False
ThisB.Text = "#"
If CurrZug Then
MyScore += CurrScore
Label1.Text = MyScore.ToString
ComputerMove()
Else
HisScore += CurrScore
Label2.Text = HisScore.ToString
End If
End Sub
Private Sub ComputerMove()
Dim TempButtonList As New List(Of Button)
For Each c As Control In FlowLayoutPanel1.Controls
If TypeOf (c) Is Button Then
Dim thisb As Button = CType(c, Button)
If thisb.Enabled Then TempButtonList.Add(thisb)
End If
Next
If TempButtonList.Count = 0 Then Exit Sub
Dim Rnd As New Random
TempButtonList(Rnd.Next(0, TempButtonList.Count - 1)).PerformClick()
End Sub
End Class
The Dim Zug As Boolean = True determines if the player or the computer is currently in queue to select a button. It is switched on every button press, so the players take turns. The ComputerMove function is executed after the player clicked a button.

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