Adding Handler using 'AddressOf' - vb.net

When trying to add an event handler to a dynamically created button I get an an error:
Dim Itm As New Button
Itm.Name = "Itm" & i
Itm.Height = 62
Itm.Width = 159
Itm.Text = Temp(i, 0).ToUpper
Itm.Left = (F * 165)
Itm.Visible = True
Itm.BackColor = Colour
Itm.ForeColor = Color.Black
AddHandler Itm.Click, AddressOf Me.Itm_Click
Me.pnlItemButton1.Controls.Add(Itm)
i = i + 1
If i > Temp.Length - 1 Then
GoTo Exit1
End If
I get an error on the AddressOf line:
"Item_Click is not a member of windowsapplication1.main"
I feel this is because I have set the name to be "Itm" & i but using AddressOf Me.Itm(i)_Click also presents an error. Any thoughts?

You have to declare the event handler Itm_Click and it must be accessible.
For example (presuming that your array Temp exists somewhere):
Public Class Demo
Protected Sub Itm_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
End Sub
Public Sub DemoMethod()
For i As Int32 = 1 To Temp.Length - 1
Dim Itm As New System.Windows.Forms.Button()
Itm.Name = "Itm" & i
Itm.Height = 62
Itm.Width = 159
Itm.Text = Temp(i, 0).ToUpper
Itm.Left = (F * 165)
Itm.Visible = True
Itm.BackColor = Colour.White
Itm.ForeColor = Color.Black
AddHandler Itm.Click, AddressOf Me.Itm_Click
Me.pnlItemButton1.Controls.Add(Itm)
Next
End Sub
End Class
You can use this event handler for all dynamically created buttons. You get the button that was clicked from the sender argument:
Protected Sub Itm_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim actualButton = Ctype(sender, System.Windows.Forms.Button)
Dim name = actualButton.Name
End Sub

Related

VB.NET MouseEventArgs for dynamiclly added controls

I'm currently trying to create a tower building tool, this is based on drag and drop functionality. I'm currently ready for the user to build his tower, but now I would also like to add the option that he can adjust his tower. This by dragging the added blocks so they swap position.
I'm currently using the flowlayoutpanel to arrange my added block's (groupboxes). These are newly created after each dragevent based on the input.
Public Class Form1
Private Sub BODY_ADD_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles _
BODY_ADD_CILINDER.MouseMove,
BODY_ADD_CONE_DOWN.MouseMove,
BODY_ADD_CONE_UP.MouseMove,
BODY_ADD_HEAD_DOWN.MouseMove,
BODY_ADD_HEAD_UP.MouseMove
' Initiate dragging.
Me.DoDragDrop(sender, DragDropEffects.Copy)
End Sub
Private Sub BODY_Arrange_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles _
BODY_LAYOUT_PANEL.MouseMove
' Initiate dragging.
Me.DoDragDrop(sender, DragDropEffects.Copy)
End Sub
Private Sub FlowLayoutPanel1_DragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles BODY_LAYOUT_PANEL.DragEnter
' Check the format of the data being dropped.
If (e.Data.GetDataPresent(GetType(PictureBox))) Then
' Display the copy cursor.
e.Effect = DragDropEffects.Copy
Else
' Display the no-drop cursor.
e.Effect = DragDropEffects.None
End If
End Sub
Private Sub BODY_LAYOUT_PANEL_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles BODY_LAYOUT_PANEL.DragDrop
Dim oPB = e.Data.GetData(GetType(PictureBox))
Dim oGB As New GroupBox
oGB.Name = "Test" & GET_BODY_ITEM_NO()
oGB.Visible = True
oGB.Width = 520
oGB.Height = 119
If oPB.name = BODY_ADD_CILINDER.Name Then
oGB.Text = "Cilinder" & GET_CILINDER_ITEM_NO()
BODY_LAYOUT_PANEL.Controls.Add(oGB)
FILL_CILINDER_GROUP_BOX(oGB)
ElseIf oPB.name = BODY_ADD_CONE_DOWN.Name Then
oGB.Text = "Cone down" & GET_BODY_ITEM_NO()
BODY_LAYOUT_PANEL.Controls.Add(oGB)
ElseIf oPB.name = BODY_ADD_CONE_UP.Name Then
oGB.Text = "Cone up" & GET_BODY_ITEM_NO()
BODY_LAYOUT_PANEL.Controls.Add(oGB)
ElseIf oPB.name = BODY_ADD_HEAD_DOWN.Name Then
oGB.Text = "Head down" & GET_HEAD_DOWN_ITEM_NO()
BODY_LAYOUT_PANEL.Controls.Add(oGB)
ElseIf oPB.name = BODY_ADD_HEAD_UP.Name Then
oGB.Text = "Head up" & GET_BODY_ITEM_NO()
BODY_LAYOUT_PANEL.Controls.Add(oGB)
End If
End Sub
Private Sub FILL_CILINDER_GROUP_BOX(ByVal oGB As GroupBox)
Dim oPB As New PictureBox
oPB.Dock = DockStyle.Left
oPB.SizeMode = PictureBoxSizeMode.StretchImage
oPB.Image = My.Resources.ResourceManager.GetObject("Cilinder")
oPB.Name = oGB.Name & "_PictureBox"
oGB.Controls.Add(oPB)
Dim oLBL1 As New Label
oLBL1.Name = oGB.Name & "_LABEL_HOOGTE"
oLBL1.Text = "Hoogte"
oLBL1.Location = New System.Drawing.Point(128, 25)
oLBL1.Width = 42
oGB.Controls.Add(oLBL1)
Dim oLBL2 As New Label
oLBL2.Name = oGB.Name & "_LABEL_DIKTE"
oLBL2.Text = "Dikte"
oLBL2.Location = New System.Drawing.Point(138, 52)
oLBL2.Width = 32
oGB.Controls.Add(oLBL2)
Dim oLBL3 As New Label
oLBL3.Name = oGB.Name & "_LABEL_ORIENTATIE"
oLBL3.Text = "Orientatie LW"
oLBL3.Location = New System.Drawing.Point(311, 25)
oLBL3.Width = 72
oGB.Controls.Add(oLBL3)
Dim oLBL4 As New Label
oLBL4.Name = oGB.Name & "_LABEL_SEGMENTEN"
oLBL4.Text = "Segmenten"
oLBL4.Location = New System.Drawing.Point(322, 52)
oLBL4.Width = 61
oGB.Controls.Add(oLBL4)
Dim oTB1 As New TextBox
oTB1.Name = oGB.Name & "_TB_HOOGTE"
oTB1.Location = New System.Drawing.Point(176, 22)
oGB.Controls.Add(oTB1)
Dim oTB2 As New TextBox
oTB2.Name = oGB.Name & "_TB_DIKTE"
oTB2.Location = New System.Drawing.Point(176, 49)
oGB.Controls.Add(oTB2)
Dim oTB3 As New TextBox
oTB3.Name = oGB.Name & "_TB_ORIENTATIE"
oTB3.Location = New System.Drawing.Point(389, 22)
oGB.Controls.Add(oTB3)
Dim oTB4 As New TextBox
oTB4.Name = oGB.Name & "_TB_SEGMENTEN"
oTB4.Location = New System.Drawing.Point(389, 45)
oGB.Controls.Add(oTB4)
End Sub
Private Function GET_BODY_ITEM_NO()
Return (BODY_LAYOUT_PANEL.Controls.Count)
End Function
Private Function GET_CILINDER_ITEM_NO()
Dim s As String
Dim y As Integer = 1
For i = 0 To BODY_LAYOUT_PANEL.Controls.Count - 1
s = BODY_LAYOUT_PANEL.Controls.Item(i).Text
If s.Contains("Cilinder") Then
y = y + 1
End If
Next
Return (y)
End Function
Private Function GET_HEAD_DOWN_ITEM_NO()
Dim s As String
Dim y As Integer = 1
For i = 0 To BODY_LAYOUT_PANEL.Controls.Count - 1
s = BODY_LAYOUT_PANEL.Controls.Item(i).Text
If s.Contains("Head down") Then
y = y + 1
End If
Next
Return (y)
End Function
End Class
For the rearranging part I would have to create a drag-event for the dynamically added groupboxes. How do you write this? How should I specify what to handle?
So the Question is: How do I hook the mouse-event to the dynamically added group-box control?
Private Sub BODY_REARRANGE_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles
Also if there are any comments on my sample code I could use some pointers!

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

Run time controls needing data back on button click

Hey all i am creating some run-time label for my form:
Dim tmpLbl As New Label
Dim intX As Integer = 0
Do Until intX = 4
With tmpLbl
.Size() = New System.Drawing.Size(58, 15)
.Text = "Run-time Controls " & intX
.Location = New System.Drawing.Point(2, 20)
.Name = "test" & intX
End With
With Me.Controls
.Add(tmpLbl)
End With
intX += 1
Loop
This works just fine... but when i want to, say place a button on the form that calls one of these run-time controls like so:
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Debug.Print(tmpLbl.Name)
End Sub
Naturally this above does not work. how can i get a labels name (ex: test2) and read its text (ex: Run-time Controls 2) when i click on that button?
Got it!
Private genTmpLbl As New List(Of Label)
Public Sub makeRunTimeControls()
Dim tmpLbl As New Label
Dim intX As Integer = 0
Do Until intX = 4
With tmpLbl
.Size() = New System.Drawing.Size(58, 15)
.Text = "Run-time Controls " & intX
.Location = New System.Drawing.Point(2, 20)
.Name = "test" & intX
End With
With Me.Controls
.Add(tmpLbl)
End With
genTmpLbl.Add(tmpLbl)
intX += 1
Loop
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
For Each label In genTmpLbl
For Each control In Me.Controls
If TypeOf (control) Is Label Then
Debug.Print(control.Name)
End If
Next
Next
End Sub

Multiple Adressof's to 1 sub

I'm trying to make a dynamic input form. But to do this I need to be able to pass multiple adressof's to 1 sub. Is this possible?
Here is my code:
Public Function AddNewcombobox() 'As System.Windows.Forms.ComboBox
Dim cmbSoort As New System.Windows.Forms.ComboBox()
Me.Controls.Add(cmbSoort)
cmbSoort.Top = cLeft
cmbSoort.Left = 62
cmbSoort.Items.Add("Maak een keuze")
cmbSoort.Items.Add("Behuizingen")
cmbSoort.Items.Add("Moederborden")
cmbSoort.Items.Add("Processoren")
cmbSoort.Items.Add("Grafische kaarten")
cmbSoort.Items.Add("Geheugen")
cmbSoort.Items.Add("DVD/Blu-ray")
cmbSoort.Items.Add("Harddisks")
cmbSoort.Items.Add("SSD")
cmbSoort.Items.Add("Voedingen")
cmbSoort.Items.Add("Invoerapparaten")
cmbSoort.Items.Add("Monitoren")
cmbSoort.SelectedIndex = 0
cmbSoort.Name = "Soort" & mintI
AddHandler cmbSoort.SelectedIndexChanged, AddressOf IndexVeranderd
Return cmbSoort
End Function
Public Sub AddNewName()
Dim cmbName As New System.Windows.Forms.ComboBox()
Me.Controls.Add(cmbName)
cmbName.Top = cLeft
cmbName.Left = 292
cmbName.Items.Add("Maak een keuze")
cmbName.Name = "Naam" & mintI
cmbName.Enabled = False
CmbPrijs.Enabled = False
txtStuks.Enabled = False
'AddHandler AddNewcombobox.SelectedIndexChanged, AddressOf IndexVeranderd
cLeft = cLeft + 40
mintI += 1
End Sub
Private Sub cmbNaam_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
'CmbPrijs.SelectedIndex = CmbNaam.SelectedIndex
End Sub
Private Sub IndexVeranderd(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim ComboVeranderd = DirectCast(sender, ComboBox)
Dim combonaam = DirectCast(sender, ComboBox)
MsgBox(combonaam.ToString)
If ComboVeranderd.SelectedIndex = 0 Then
'ComboNaam.Enabled = False
txtStuks.Enabled = False
End If
For i = 0 To EasybyteDataSet.Stock.Rows.Count - 1
If ComboVeranderd.SelectedItem = EasybyteDataSet.Stock.Rows(i)("Soort") Then
'ComboNaam.Enabled = True
txtStuks.Enabled = True
'ComboNaam.Items.Add(EasybyteDataSet.Stock.Rows(i)("Product naam"))
CmbPrijs.Items.Add(EasybyteDataSet.Stock.Rows(i)("Prijs"))
End If
Next
End Sub
When cmbSoort's index changes, it should send both cmbSoort and cmbName to the sub IndexVeranderd.
The trick is, cmbSoort and cmbName are generated by the functions when the user presses a button.
Is this possible?
To make a Sub handle multi combobox ..
In your case :
Public Sub AddNewcombobox()
Dim cmbSoort as New ComboBox
Dim cmbName as New ComboBox
'.......... fill cmbSoort properties
'.......... fill cmbName properties
Controls.Add(cmbSoort)
AddHandler cmbSoort.SelectedIndexChanged, AddressOf IndexVeranderd
Controls.Add(cmbname)
AddHandler cmbName.SelectedIndexChanged, AddressOf IndexVeranderd
End Sub
And the Sub handler
Private Sub IndexVeranderd(ByVal sender As System.Object, ByVal e As System.EventArgs)
Select Case oCB
Case cmbSoort
' ................. code here
Case cmbName
' ................. code here
End Select
End Sub
The names seem to have an number added to them if they are the same so that Soort1 is tied to Naam1 then just separate out the number and access the control directly. This way you only need the handler for cmbSoort.
Dim ComboVeranderd = DirectCast(sender, ComboBox)
Dim combonaam = Me.Controls("Naam"+ComboVeranderd.Name.Substring(ComboVeranderd.Name.Length-1))
I assumed the number is only 1 digit, if not you might have to adjust for more.
If the names don't include a number this would be an efficient way to pair them up

How to find and update a matching control once a file exists

I have written a WinForm project which displays a ListBox containing a list of file names. When the user clicks a submit button, the application dynamically loads and displays one PictureBox control for each file and then waits while they are processed. As PDF files are generated for each one, the matching PictureBox for that file needs to be updated to display an image.
Here's what I have so far:
Private Sub ButtonSubmit_Click(sender As System.Object, e As System.EventArgs) Handles ButtonSubmit.Click
Dim x As Integer = 790
Dim y As Integer = 91
For i As Integer = 0 To ListBox1.Items.Count - 1
Dim key As String = ListBox1.Items(i).ToString()
'adds picturebox for as many listbox items added
Dim MyPictureBox As New PictureBox()
MyPictureBox.Name = "pic" + key
MyPictureBox.Location = New Point(x, y)
MyPictureBox.Size = New Size(12, 12)
MyPictureBox.SizeMode = PictureBoxSizeMode.StretchImage
Me.Controls.Add(MyPictureBox)
MyPictureBox.Image = My.Resources.Warning1
ToolTipSpooling.SetToolTip(MyPictureBox, "Creating PDF...")
x += 0
y += 13
Next i
Call CheckPDFs()
End Sub
Public Sub CheckPDFs()
Dim ListboxTicketIDs = (From i In ListBox1.Items).ToArray()
For Each Item In ListboxTicketIDs
Dim ID = Item.ToString
Dim Watcher As New FileSystemWatcher()
Watcher.Path = "C:\Temp\"
Watcher.NotifyFilter = (NotifyFilters.Attributes)
Watcher.Filter = ID + ".pdf"
AddHandler Watcher.Changed, AddressOf OnChanged
Watcher.EnableRaisingEvents = True
Next
End Sub
Private Sub OnChanged(source As Object, e As FileSystemEventArgs)
Dim p As PictureBox = CType(Me.Controls("pic" + ListBox1.Items.ToString()), PictureBox)
p.Image = My.Resources.Ok1
End Sub
I'm having trouble changing the PictureBox to a different picture once the item(s) listed in the listbox are present, based on the FileSystemWatcher. For instance, the files are not always created in the same order as they exist in the ListBox.
EDIT
Working code below.
Public Class Form1
Private WithEvents Watcher As FileSystemWatcher
Public Sub CheckPDFs()
For i As Integer = 0 To ListBox1.Items.Count - 1
Watcher = New FileSystemWatcher()
Watcher.SynchronizingObject = Me
Watcher.Path = "C:\Temp\"
Watcher.NotifyFilter = NotifyFilters.Attributes
Watcher.Filter = "*.pdf"
Watcher.EnableRaisingEvents = True
Next
End Sub
Private Sub Watcher_Changed(ByVal sender As Object, ByVal e As FileSystemEventArgs) Handles Watcher.Changed
Dim key As String = Path.GetFileNameWithoutExtension(e.Name)
Dim p As PictureBox = CType(Me.Controls("pic" + key), PictureBox)
p.Image = My.Resources.Ok
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
ListBox1.Items.Add(TextBox1.Text)
TextBox1.Text = ""
Dim x As Integer = 5
Dim y As Integer = 5
For i As Integer = 0 To ListBox1.Items.Count - 1
Dim key As String = ListBox1.Items(i).ToString()
'adds picturebox for as many listbox items added
Dim MyPictureBox As New PictureBox()
MyPictureBox.Name = "pic" + key
MyPictureBox.Location = New Point(x, y)
MyPictureBox.Size = New Size(15, 15)
MyPictureBox.SizeMode = PictureBoxSizeMode.StretchImage
Me.Controls.Add(MyPictureBox)
MyPictureBox.Image = My.Resources.Info
x += 0
y += 18
Next i
Call CheckPDFs()
End Sub
First of all, you don't need to create multiple file watchers. You just need a single file watcher to watch for any changes to the folder. I would recommend declaring it as a private field at the top of your form using the WithEvents keyword so you don't have to worry about adding and removing event handlers.
Next, when the watcher raises the changed event, you can get the file name of the file that changed by looking at the properties of the event args object. You need to get the name of the file that changed and then use the file name as the key to finding the matching picture box control.
Public Class Form1
Private WithEvents Watcher As FileSystemWatcher
Public Sub CheckPDFs()
Watcher = New FileSystemWatcher()
Watcher.Path = "C:\Temp\"
Watcher.NotifyFilter = NotifyFilters.Attributes
Watcher.Filter = "*.pdf"
End Sub
Private Sub Watcher_Changed(ByVal sender As Object, ByVal e As FileSystemEventArgs) Handles Watcher.Changed
Dim key As String = Path.GetFileNameWithoutExtension(e.Name)
Dim p As PictureBox = CType(Me.Controls("pic" + key), PictureBox)
p.Image = My.Resources.Ok1
End Sub
End Class
However, since you say in a comment below that the file name will not be the same as the text in the listbox, but that it will merely start with that text, you could do something like this, instead:
Private Sub Watcher_Changed(ByVal sender As Object, ByVal e As FileSystemEventArgs) Handles Watcher.Changed
Dim p As PictureBox = Nothing
For Each item As Object In ListBox1.Items
If e.Name.StartsWith(item.ToString()) Then
p = CType(Me.Controls("pic" + item.ToString()), PictureBox)
Exit For
End If
Next
If p IsNot Nothing Then
p.Image = My.Resources.Ok1
End If
End Sub