Where are my dynamically added buttons(VB.NET)? - vb.net

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.

Related

Programmatically made button destroying itself

I'm trying to make a button that is programmatically created and when clicked it can destroy itself (and other programmatically made objects).
This is the sub that is called to create the button (alongside two other textboxes ive removed from this code)
Public Sub createProduct(i As Integer)
'Creating the button to be able to Delete the product
'i is used as a way to keep track of each row of products
Dim DeleteProduct As Button = New Button
With DeleteProduct
.Size = New Size(20, 20)
.Location = New Point(240, 50 + (i * 25))
.Text = New String("-")
.Name = "btnRemoveProduct" + i.ToString
UserButtons.Add(DeleteProduct)
End With
Me.Controls.Add(DeleteProduct)
AddHandler DeleteProduct.Click, AddressOf DeleteProductButton
End Sub
Which links the button to this code
Friend Sub DeleteProductButton(sender As Object, e As EventArgs)
End Sub
However, I can't find any way to be able to refer to the button (and the other textboxes) in the DeleteProductButton sub, and therefore can't delete them once the button is pressed.

Creating multiple click events for dynamic buttons in vb.net

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

VB.Net: Using and addressing buttons in TableLayoutPanel

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

Simple VB, handling many buttons

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

How to change only one tooltip?

I am populating a FlowLayout with Pictureboxes. As I populate i give each of them a tooltip. I have a seperate function to change the pictures how can I change the tooltip as well?
dim laytt as tooltip = new tooltip
For i = 1 To count
Dim newPic As PictureBox = New PictureBox()
newPic.Image = p.Image
newPic.Size = p.Size
newPic.SizeMode = p.SizeMode
laytt.SetToolTip(newPic, ttstring)
AddHandler newPic.Click, AddressOf LayoutComponent_Clicked
sys.Add(a_component)
LayoutFlowLayout.Controls.Add(newPic)
Next
later i have a function to change the pics in it I want to be able to change the tool tip
Private Sub LayoutComponent_Clicked(ByVal sender As Object, ByVal e As EventArgs)
Dim i As Integer = LayoutFlowLayout.Controls.IndexOf(sender)
If deleteModeOn Then
sys.components.RemoveAt(i)
LayoutFlowLayout.Controls.RemoveAt(i)
Exit Sub
End If
'get index in sys from layout?
If (sys.components.Item(i).GetType() = GetType(Transpositor)) Then
Form2.ShowDialog(Me)
sys.components.Item(i).divert = tempTranspositorDivert
'here I want to do something like this
laytt.RemoveAt(i) <--- THIS DOESN'T EXIST
End If
End Sub
TL;DR I want to remove/change only one tooltip text at a specific index
Since the sender parameter is the picture box control that was clicked, you can use that variable to specify which control you want to alter. For instance, this will remove the tool tip:
laytt.SetToolTip(sender, Nothing)
This will change it:
laytt.SetToolTip(sender, "new value")