vb.net runtime buttons and "AddressOf " parenthese - vb.net

in my system i am creating runtime buttons, i have create one sub to create all buttons which is fine for what i need however they all go to the same "addressOf" i want to create separate handlers, however it doesnt allow with my current method any one know a simple workaround id prefer not to change the actual structure that i have, thanks
sorry dont know why this part is being weird
private Sub Button(ByVal x As Integer, ByVal y As Integer, ByVal name As String, ByVal title As String, ByVal hieght As Integer, ByVal width As Integer, ByVal buttonAddress As String)
Dim btn As Button
btn = New Button
With btn
.Location = New Point(x, y)
.Text = title
.Name = name
.Width = width
.Height = hieght
Controls.Add(btn)
AddHandler btn.Click, AddressOf "BtnOperation_" & buttonAddress
End With
End Sub
Public Sub BtnOperation_AddAppointment(ByVal sender As Object, ByVal e As EventArgs)
Dim btn As Button = DirectCast(sender, Button)
Dim name = btn.Name
Select Case name
Case "Cfind_Btn"
'when the Cfind_btn is pressend it create a Csearch textbox at runtime
btn.Visible = False
GetFormType("add_CfindOK")
CreateTxtTypeBox(BoxType.Combo_box, "CSearch_Box")
Case "add_CfindOK"
Case ("Cnew_Btn")
'open the add customer form that connects to the mysql database'
End Select
'fetch the btn.name'
' then with the name use "select case" to get appropreate action of the btn. '
End Sub

Pass the handler into your Button factory method:
private Sub Button(ByVal x As Integer, ByVal y As Integer, ByVal name As String, ByVal title As String, ByVal hieght As Integer, ByVal width As Integer,
clickHandler As System.EventHandler)
Dim btn As Button
btn = New Button
With btn
.Location = New Point(x, y)
.Text = title
.Name = name
.Width = width
.Height = hieght
Controls.Add(btn)
AddHandler btn.Click, clickHandler
End With
End Sub
Then, when you call Button use AddressOf to pass in the correct handler:
Button(0,0,"MyButton".....,AddressOf BtnOperation_AddAppointment)

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)

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 make a Label using vb code by clicking button

I want to add a label to the form with a click of the button.
When I use that code here, it only adds 1 label but I want to add unlimited amount every time I click the button; it even adds 1 label even if I change the name.
Thank you every one.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim lbl As New label
lbl.Size = New System.Drawing.Size(159, 23) 'set your size
lbl.Location = New System.Drawing.Point(12, 180) 'set your location
lbl.Text = (TextBox1.Text) 'set your name
Me.Controls.Add(lbl) 'add your new control to your forms control collection
End Sub
Just a rehash of the previous 2 perfectly good answers. Here it tries to make clear that at least the location and text must be set based on logic provided by the user
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
' YOU decide where EACH new label goes and pass the X,Y for each
' new label; YOU decide on the text and pass it. you can make them
' variables, but YOU have to do some of the thinking....
' <...> == information YOU provide
Private x As integer = <where you want the new label>
Private y as integer = <where you want the new label>
Private txt as String = <Text for this new label>
' EXAMPLEs
' a) set text from a textbox
' txt = txtLblText.Text
' b) Set X position from another code integer variable
' x = thisX
' c) Set Y position from textbox input
' y = Integer.Parse(txtLblYPos.Text)
Dim lbl as Label = MakeNewLabel(x, y, txt As string)
Me.Controls.Add(lbl)
End Sub
Friend function MakeNewLabel(x as integer, y as Integer, txt As String) as label
Dim lbl As New label
' add other label props here as needed
lbl.Size = New System.Drawing.Size(159, 23) 'set your size
lbl.Location = New System.Drawing.Point(x, y) 'set your location
lbl.Text = txt
Return lbl
End Function
As correctly pointed out by #jlvaquero, you are overlapping your labels. The reason for this is that you're not changing the Point where these labels are being added to the Form.
One solution is to have field variables that can adjust the Point.
Private x As Integer = 12
Private y As Integer = 180
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim lbl As New label
lbl.Size = New System.Drawing.Size(159, 23) 'set your size
lbl.Location = New System.Drawing.Point(x, y) 'set your location
lbl.Text = (TextBox1.Text) 'set your name
Me.Controls.Add(lbl) 'add your new control to your forms control collection
x += 10 'arbitrary value, you could adjust y, too
End Sub
hello and thank you everyone for your great help i would no got that far without you her si the code that i used
Public Class Form1
Dim counter As Integer = 1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim lbl As New Label
lbl.Name = "Label" & counter
lbl.Size = New Size(150, 20)
lbl.Location = New Point(200, counter * 22)
lbl.Text = TextBox1.Text 'text on label
Me.Controls.Add(lbl)
counter += 1
End Sub
End Class

Thread Safe Calls on Forms Controls Array

I am trying to access a dynamically generated Control from a separate thread.
But I am always getting a "Stack Overflow Exception" with my code.
I am using following code:
Private _workerThread As Threading.Thread
Private Sub Main_Load(sender As Object, e As System.EventArgs) Handles Me.Load
Dim Label As New Label
Label.Name = "Label1"
Label.Location = New System.Drawing.Point(12, 12)
Label.Text = String.Empty
Label.AutoSize = True
Controls.Add(Label)
_workerThread = New Threading.Thread(AddressOf DoWork)
_workerThread.Priority = Threading.ThreadPriority.BelowNormal
_workerThread.Start()
End Sub
Private Sub DoWork()
SetLabelText("Label1", "text")
End Sub
Delegate Sub SetLabelTextCallback(ByVal LabelName As String, ByVal text As String)
Private Sub SetLabelText(ByVal LabelName As String, ByVal text As String)
If CType(Me.Controls(LabelName), Label).InvokeRequired Then
Dim d As New SetLabelTextCallback(AddressOf SetLabelText)
d.Invoke(LabelName, text)
Else
CType(Me.Controls(LabelName), Label).Text = text
End If
End Sub
Apparently InvokeRequired never gets to False. But I can´t get it why.
Maybe someone can tell me what I´m doing wrong.
You are not calling the method SetLabelTextCallback on the thread of the Label,
thus you will recall again on the same thread and InvokeRequired is never false
Delegate Sub SetLabelTextCallback(ByVal LabelName As String, ByVal text As String)
Private Sub SetLabelText(ByVal LabelName As String, ByVal text As String)
Dim l as Label = CType(Me.Controls(LabelName), Label)
if l.InvokeRequired then
Dim d As New SetLabelTextCallback(AddressOf SetLabelText)
l.Invoke(d, new Object() {LabelName, text} )
Else
l.Text = text
End If
End Sub

Creating buttons in runtime from Database field

I have a single columns table which holds 50 records. I would like to create 50 buttons from those records. How can I do that in Vb.Net?
Any help will be appreciated.
Assuming you mean Winforms:
Use your Datasource(f.e. a DataTable) and loop its RowCollection. For example:
Private Sub BtnLoadButtons_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnLoadButtons.Click
Dim source As New DataTable("MyButtonTable")
source.Columns.Add(New DataColumn("MyButtonColumn", GetType(String)))
For i As Int32 = 1 To 50
Dim newRow As DataRow = source.NewRow
newRow("MyButtonColumn") = "Button_" & i
source.Rows.Add(newRow)
Next
'you are loading the above DataTable from SQL-Server, now iterate the rows...'
For Each row As DataRow In source.Rows
Dim btn As New Button()
btn.Name = DirectCast(row("MyButtonColumn"), String)
btn.Text = btn.Name
btn.Location = New Point(0, Me.Panel1.Controls.Count * btn.Height)
AddHandler btn.Click, AddressOf handleButton
Me.Panel1.Controls.Add(btn)
Next
End Sub
Private Sub handleButton(ByVal sender As Object, ByVal e As EventArgs)
Dim btn As Button = DirectCast(sender, Button)
'do something ...'
End Sub
If you are working in a Winforms application you can use the FlowLayoutPanel because it automatically orders the button layouts for you:
dim i as integer=1
for each record in Table
dim btn as new Button
btn.id = "btn" & i
i+=1
Panel1.Controls.add(btn)
next