When creating a button I want to create a click event for each button. How do I create a click event for each button created dynamically? Here is my code. It works to create a single event based on the first button created.
Sub CreateDynamicButton()
Dim ButtonNumber As Integer = 1
Dim axisX As Integer = 53
Dim axisY As Integer = 13
' Create a Button object
Do Until ButtonNumber = 11
Dim dynamicButton As New Button
' Set Button properties
dynamicButton.Location = New Point(axisX, axisY)
dynamicButton.Height = 30
dynamicButton.Width = 200
' Set background and foreground
dynamicButton.BackColor = Color.Beige
dynamicButton.ForeColor = Color.Black
dynamicButton.Text = "I am Dynamic Button" & ButtonNumber
dynamicButton.Name = "DynamicButton" & ButtonNumber
dynamicButton.Font = New Font("Georgia", 10)
AddHandler dynamicButton.Click, AddressOf dynamicButton_Click
' Add Button to the Form. Placement of the Button
' will be based on the Location and Size of button
Controls.Add(dynamicButton)
axisY = axisY + 35
ButtonNumber = ButtonNumber + 1
Loop
'Add Exit Button
Dim dynamicButtonExit As New Button
' Set Button properties
dynamicButtonExit.Location = New Point(axisX, axisY)
dynamicButtonExit.Height = 30
dynamicButtonExit.Width = 200
' Set background and foreground
dynamicButtonExit.BackColor = Color.Beige
dynamicButtonExit.ForeColor = Color.Black
dynamicButtonExit.Text = "Exit"
dynamicButtonExit.Name = "Exit"
dynamicButtonExit.Font = New Font("Georgia", 10)
AddHandler dynamicButtonExit.Click, AddressOf dynamicButtonExit_Click
' Add Button to the Form. Placement of the Button
' will be based on the Location and Size of button
Controls.Add(dynamicButtonExit)
End Sub
You don't need to create multiple event to handle your dynamic buttons, dynamicButton_Click is enough to handle all click. Better give ID for each button and you only need to do is in this event, do code as below:
Dim btn As Button = DirectCast(sender, Button)
If btn.ID = "DynamicButton1" then
'Do logic here for button 1
End If
You just need to add a little logic to handle each button click in the one event handler. If you use as 'Select Case' Statement it keeps things tidy as well.
If you have a lot of code for each button's logic, it may be better to write separate subs for each button and call the appropriate sub using each 'Case' block like in the second case block
Private Sub DynamicButton_click(sender As Object, e As EventArgs)
Dim btn As Button = DirectCast(sender, Button)
Select Case btn.Name
Case "DynamicButton1"
MessageBox.Show("button1")
Case "DynamicButton2"
dynamicbutton2_Click(sender, e)
End Select
End Sub
Private Sub dynamicbutton2_Click(sender As Button, e As EventArgs)
MessageBox.Show("Button2")
'and lots of other code
End Sub
Related
So here's what I have:
Code that makes buttons when you click the button "New Button" (Button1).
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
ActionsMade = ActionsMade + 1
Dim actionButton = New Windows.Forms.Button
ActionContainer.Controls.Add(actionButton)
actionButton.Text = "New Action " + ActionsMade.ToString
actionButton.Width = 107
actionButton.Height = 56
AddHandler actionButton.Click, AddressOf OnActionButtonClick
End Sub
When you click the buttons that were created, it shows an input box, where you type what you want to rename the button to.
Sub OnActionButtonClick()
If IsRenaming Then
Dim renameTo As String
renameTo = InputBox("Rename ActionButton To:")
Else
MessageBox.Show("Action started! Not renaming")
End If
End Sub
The only problem is, I have no way to identify between these buttons.
tl;dr:
I created buttons programmatically
I want to rename them
I don't know how to identify between these buttons and rename them individually
This is more concise and includes a referencable button name (eg Button_03):
Private Sub MakeButton_Click(sender As Object, e As EventArgs) Handles MakeButton.Click
Static ActionsMade As Integer = 0
ActionsMade += 1
ActionContainer.Controls.Add(New Button With {
.Name = $"Button_{ActionsMade:00}",
.Text = $"New Action {ActionsMade:00}",
.Size = New Size(107, 56),
.Location = New Point(100, 250 + 25 * ActionsMade)
})
AddHandler ActionContainer.Controls($"Button_{ActionsMade:00}").Click, AddressOf OnActionButtonClick
End Sub
Note that in the above code I haven't actually defined a new button per se, just New-ed it within the Controls.Add() statement, and then used the generated button name to add the event handler.
Another way would be declare the button as an independent object and then add it:
Dim actionButton As New Button With {
.Name = $"Button_{ActionsMade:00}",
.Text = $"New Action {ActionsMade:00}",
.Size = New Size(107, 56),
.Location = New Point(100, 250 + 25 * ActionsMade)
}
ActionContainer.Controls.Add(actionButton)
AddHandler actionButton.Click, AddressOf OnActionButtonClick
Other notes:
Use of a Static ActionsMade integer variable which retains its value between calls. This could also be a module-wide variable and removed from the MakeButton_Click Sub.
Use of string interpolation in assigning the button's Name and Text properties according to a formated version of the ActionsMade value.
Use of button properties Size and Location.
Automatic increment of button vertical position based on the value of ActionsMade.
Regarding your Action Button event handler, it should look like this:
Private Sub OnActionButtonClick(sender As Object, e As EventArgs)
If ActionStarted Then
MessageBox.Show("Action started! Not renaming.")
Else
CType(sender, Button).Text = InputBox("Rename ActionButton To:")
End If
End Sub
Note that I've checked for a started Action rather than a renaming in progress but that's just an illustration of an alternative approach. Note also that you don't need to know the name of the button to change its properties.
I need to set the background color of Infragistics.Win.UltraWinEditors.UltraDateTimeEditor to yellow when the time is not today, for example. Also, I need to show a warning message when I move the cursor over the editor. I know XAML has such property I can use. How about in winform?
A quick example on how you could accomplish your goal. I am pretty sure that there are other ways to get this done, but this works
' Globals controls and Forms
Dim f As Form
Dim dt As Infragistics.Win.UltraWinEditors.UltraDateTimeEditor
Dim tt As Infragistics.Win.ToolTip
' This Main has been built using LinqPAD, you could have problems
' running it, as is in a WinForms project, but the concepts are the same
Sub Main()
dt = New UltraDateTimeEditor()
dt.Dock = DockStyle.Top
' Add the event handlers of interest to the UltraDateTimeEditor
AddHandler dt.Validating, AddressOf onValidating
AddHandler dt.Enter, AddressOf onEnter
tt = New Infragistics.Win.ToolTip(dt)
' Just another control to trigger the OnEnter and Validating events
Dim b = New Button()
b.Dock = DockStyle.Bottom
f = New Form()
f.Size = New Size(500, 500)
f.Controls.Add(dt)
f.Controls.Add(b)
f.Show()
End Sub
Sub onValidating(sender As Object , e As EventArgs)
' Some condtions to check and then set the backcolor as you wish
dt.BackColor = Color.Yellow
End Sub
Sub onEnter(sender As Object, e As EventArgs)
' Set the background back
dt.BackColor = Color.White
' Some condition to check to display the tooltip
If dt.DateTime <> DateTime.Today Then
tt.ToolTipText = "Invalid date"
' Time to leave the message visible
tt.AutoPopDelay = 2000
tt.DisplayStyle = ToolTipDisplayStyle.BalloonTip
' Calculation to set the tooltip in the middle of the editor
Dim p = New Point(dt.Left + 50, dt.Top + (dt.Height \ 2))
p = dt.PointToScreen(p)
' Show the message....
tt.Show(p)
End If
End Sub
Hi I have this TablelayoutPanel setup currently in my program to create a grid of buttons that will later correspond to a specific column and row:
'****INITIALISES TABLE LAYOUT INTO FORM******
Dim ColCount, RowCount As Integer
'Later change so that values are automatically calculated
ColCount = 5
RowCount = 5
'*********Copy and pasted from site as example, CHANGE LATER*******
Haztable = New TableLayoutPanel
Haztable.AutoScroll = True
Haztable.Dock = DockStyle.Fill
Haztable.ColumnCount = ColCount
Haztable.RowCount = RowCount
For rowNo As Integer = 0 To Haztable.RowCount - 1
For columnNo As Integer = 0 To Haztable.ColumnCount - 1
'Dim ctrl As Control = New Button
'ctrl.Text = String.Format("{0} {1},{2}", ctrl.GetType().Name, columnNo, rowNo)
'ctrl.Size = New Size(20, 20)
'Haztable.Controls.Add(ctrl, columnNo, rowNo)
Dim buttonname As String
buttonname = "B" & columnNo & rowNo
Dim button As Control = New Button
button.Size = New Size(70, 20)
button.Name = buttonname
button.Text = buttonname
Haztable.Controls.Add(button, columnNo, rowNo)
AddHandler button.Click, AddressOf buttonname_Click
Next
Next
Me.Controls.Add(Haztable)
Call buttonfind()
And this all works, creating a grid of buttons, much like the layout of an excel spreadsheet.
The buttons are named according to their XY position (e.g. the button in (1,1) would be called "B11") but the problem is I can't seem to work out how I can address these buttons i.e
*If B(X.Y) is clicked then save boolean value that button at X,Y is pressed.
It would be great to have one algorithm to scan and check if any buttons have been pressed instead of using "Select Case" for each button.
I would just create the buttons in the designer but for my full code i'm going to need 1000+ buttons and that seems an inefficient way to do so.
Your buttonname_Click should have a Sender object which is the Button that you Clicked just cast it to a Button and check the name then.
Private Sub buttonname_Click(sender As System.Object, e As System.EventArgs)
Dim btn As Button = CType(sender, Button)
Select Case btn.Name
Case "B11"
'Do something
Case "B12"
'Do Something esle
'...........
End Select
End Sub
Based on your last statement see if this works you may need to build an Array or a List if you need to reference the Text elsewhere in your Program
Private Sub buttonname_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim btn As Button = CType(sender, Button)
If btn.Text = "H" Then
btn.Text = "M"
ElseIf btn.Text = "M" Then
btn.Text = "L"
ElseIf btn.Text = "L" Then
btn.Text = ""
Else
btn.Text = "H"
End If
End Sub
You have add clicked event and handle each of them by using their row and column number. Make yourself a new button first so that you can access row and column numbers with spending no effort to parse column and row numbers from the controls name:
Public Class NewButton
Inherits Button
Public Row, Column, ClickCount as Integer
End Class
Now create and handle:
Public Class Form1
Sub addbuttons()
Dim newbut As New NewButton
newbut.Name = "B12"
newbut.Row = "1"
newbut.Column = "2"
'and other properties...
AddHandler newbut.Click, AddressOf clicked
Me.Controls.Add(newbut)
End Sub
Sub clicked(sender As System.Object, e As System.EventArgs)
Dim x As NewButton = DirectCast(sender, NewButton)
If x.Column = 2 And x.Row = 1 Then
x.ClickCount += 1
End If
End Sub
End Class
In my VB solution I have a lot of buttons arranged in a grid. When the program is loaded one of the buttons is randomly set to be the right one (You have to click that one to win). Can anybody point my in the right direction? Because there must be a better way than manually coding every single button, and creating an event handler for every single button.
You don't have to give me a working example, just an overall idea of how this is done.
Thanks.
If you want to arrange the buttons in a grid, either use the TableLayoutPanel or add the buttons directly to the form and calculate their positions. The TableLayoutPanel is useful if you want to arrange the buttons automatically when the form resizes, otherwise adding the buttons directly seems easier to me.
Add the buttons to an array defined at form level to make them easily accessible
Public Const NColumns As Integer = 5, NRows As Integer = 4
Private buttons As Button(,) = New Button(NColumns - 1, NRows - 1) {}
You can add the buttons easily in loops
For ix As Integer = 0 To NColumns - 1
For iy As Integer = 0 To NRows - 1
Dim btn = New Button()
btn.Text = String.Format("{0:d2}{1:d2}", ix, iy)
btn.Location = New Point(leftMargin + ix * xDistance,
topMargin + iy * yDistance)
btn.Size = New Size(buttonWidth, buttonHeight)
AddHandler btn.Click, Addressof Button_Clicked
buttons(ix, iy) = btn
Controls.Add(btn)
Next
Next
You can determine the winning button with a random generator. Define it as form member, not as local variable.
Private randomGenrator As System.Random = New System.Random()
Determine the coordinates
Dim xWins = randomGenrator.Next(NColumns) 'Returns a number between 0 and NColumns-1
Dim yWins = randomGenrator.Next(NRows)
The click handler looks like this
Private Sub Button Button_Clicked(sender As Object, e As EventArgs)
If sender = buttons(xWins, yWins) Then
'You win
Else
'You loose
End
End Sub
First, you said you want a grid of buttons, so you have to have a FlowLayoutPanel control in your form in order to let the buttons you want to add, to be arranged automatically.
Second, you have to make use of a for loop, r any kind of look, in order to add the buttons to be added to previously added 'FlowLayoutPanel'.
class Answers
Dim strAnswerText as string
Dim AnswerFlag as Boolean
End Class
Sub LoadForm(byval a_Answers as Answer())
Dim i as Integer = 0
Dim b as Button
For(i=0;i<NUM_OF_BUTTONS;i++)
b = New Button()
b.Text = "Choice -" & i & "- " & a_Answers(i).strAnswerText
b.Tag = a_Answers(i).AnswerFlag
'Supposing that the FlowLayoutPanel control name is fl
AddHandler b.Click, Addressof Clicked
fl.controls.Add(b)
End For
End Sub
Sub Button Clicked(sender as object, e as EventArgs)
if sender.Tag = True
'True answer
else
'Wrong answer
end if
End Sub
I have come across an issue that has completely bamboozled me.
I have a dynamically added DataGridView with many columns and rows and what I am trying to achieve is on mouse_up I want a button to be drawn over the selected cells. So for example if I select the first 3 cells of row3, a button should be drawn over the 3 cells.
I have tried using the X and Y of each selected cell and convert it to a buttoncolumn but that didn't work. What I currently have is sample code that just adds button to the screen but they do not appear on the screen (thus the title). Once I get the buttons to appear on the screen I will then try to draw them over the selected cells but I need to get over this hurdle first
This is the code I am using:
'I dynamically add the DataGridView
Grid = New DataGridView
Grid.Dock = DockStyle.Fill
Grid.BackgroundColor = Color.White
Grid.RowHeadersVisible = False
Grid.AllowUserToOrderColumns = False
Grid.AllowUserToResizeRows = False
...
TabControl.SelectedTab.Controls.Add(Grid)
AddHandler Grid.CellMouseUp, AddressOf Grid_MouseUp
...
'On mouse up it calls the sub to add buttons
Private Sub Grid_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs)
Dim i As Integer
For i = 1 To 30
NewButton(i) 'calls the dub
Next i
End Sub
'this is the sub
Private Sub NewButton(ByVal ButtonNumber As Integer)
Dim oButton As Button
oButton = New Button
oButton.Enabled = True
oButton.Location = New Point(ButtonNumber + 50, ButtonNumber + 50)
oButton.Name = "MyButton" & ButtonNumber.ToString
oButton.Size = New Size(75, 23)
oButton.Text = "Button" & ButtonNumber.ToString
oButton.Visible = True
oButton.Tag = ButtonNumber
TabControl.SelectedTab.Controls.Add(oButton)
End Sub
I would appreciate it if you guys could suggest what I need to change in order to achieve this functionality.
Thanks for your time
Maybe you button is Under the other controls, try calling oButton.BringToFront() after you add the button to the Tabcontrol controls.