How to retrieve text from dynamic label and display it to message box using dynamic button? - vb.net

I have these codes retrieving data from mysql database and display it into the dynamic panels, labels, and buttons. The problem is I don't know how to retrieve those texts from labels(lblProductName) to display it into message box when clicking the dynamic buttons(btnAddto). TIA!
Imports MySql.Data.MySqlClient
Module mdlMenu
Dim Cpanel As Panel
Dim lblProductName As Label
Dim btnAddto As Button
Dim count As Integer
Public Sub LoadMenu()
Try
SQLConnection()
With sqlcom
.CommandText = "SELECT * FROM tblproduct"
.Connection = sqlconn
End With
Dim datareader As MySqlDataReader = sqlcom.ExecuteReader
Do While datareader.Read()
Cpanel = New Panel()
With frmMenu
count = .TableLayoutPanel1.Controls.OfType(Of Panel)().ToList().Count
Cpanel.Location = New Point(10, (25 * count) * 7)
Cpanel.Size = New Size(450, 160)
Cpanel.Name = "Cpanel" & count
Cpanel.AutoScroll = True
Cpanel.BackColor = Color.White
.TableLayoutPanel1.Controls.Add(Cpanel)
lblProductName = New Label()
lblProductName.Location = New Point(165, 10)
lblProductName.AutoSize = True
lblProductName.Name = "lblProd" & count
lblProductName.Text = datareader.Item("ProductName").ToString & count
lblProductName.Font = New Font(lblProductName.Font.FontFamily, 14, FontStyle.Bold)
Cpanel.Controls.Add(lblProductName)
btnAddto = New Button()
btnAddto.Location = New Point(180, 115)
btnAddto.Size = New Size(80, 40)
btnAddto.Name = count
btnAddto.Text = count
btnAddto.Tag = count.ToString
btnAddto.Font = New Font(btnAddto.Font.FontFamily, 10, FontStyle.Bold)
AddHandler btnAddto.Click, AddressOf btnAddto_Click
Cpanel.Controls.Add(btnAddto)
count += 1
End With
Loop
Catch ex As Exception
MsgBox(ex.Message)
Finally
sqlconn.Close()
sqlconn.Dispose()
End Try
End Sub

There are a couple of concepts here:
How to reference a dynamic control
How to bind an event to a dynamic control
Regarding number 1 on how to reference a dynamic control, it looks like you are declaring a form level variable and setting the value. So you should be able to reference lblProductName after it is set in the LoadMenu method. However, if you did not want to create a form level variable, you could simply use the Controls.Find method (documentation).
Regarding number 2 on how to bind an event to a dynamic control, you would use the AddHandler statement (documentation), which it looks like you are already doing here:
AddHandler btnAddto.Click, AddressOf btnAddto_Click
So what would the btnAddto_Click method look like putting it all together?
Private Sub btnAddto_Click(sender As Object, e As EventArgs)
Dim button = DirectCast(sender, Button)
Dim count = If(button.Tag IsNot Nothing, button.Tag.ToString(), String.Empty)
Dim labels = Controls.Find("lblProd" & count, True)
If (labels.Length > 0) Then
Dim label = labels(0)
MessageBox.Show(label.Text)
End If
End Sub

Related

Can't display Data in ComboBox Control of DropDownStyle (DropDownList)

I have the following requirement,
I have a ComboBox Control (DropDownList Style) which user has to select a given value, but can not edit. Then I save it to a Database Table, and it's working fine.
(dataRow("it_discount_profile") = Trim(cmbDisProfile.Text))
But when I try to show the same Data in the same ComboBox by retrieving it from the Database, it won't show.
(cmbDisProfile.Text = Trim(tempTb.Rows(0).Item("it_discount_profile")))
When I change the ComboBox to "DropDown Style", it works. But then the User can edit it.
Am I missing something here or is it like that? Any advice will be highly appreciated.
Im filling it in runtime using a procedure.
Private Sub filldisProfiles()
Dim sqlString As String = "SELECT discount_profile FROM tb_discount_profiles"
Dim tempTb As DataTable
Dim myTbClass As myClassTableActivities = New myClassTableActivities()
tempTb = myTbClass.myFunctionFetchTbData(sqlString)
cmbDisProfile.DataSource = tempTb
cmbDisProfile.DisplayMember = "discount_profile"
End Sub
Ok. Actually, Im trying to migrate one of my old project from VB to VB.Net. VB.Net is little new to me. Im using a self built classto reduce codes in other places. Im attaching the class below.
My actual requirement is to populate the combo box from a table. I like to do it in run time. I don't want users to edit it. If they want to add a new value, they have separate place (Form) for that. I think im doing it in a wrong way. If possible please give a sample code since I'm not familiar with the proposed method.
Public Function myFunctionFetchTbData(ByVal inputSqlString As String) As DataTable
Try
Dim SqlCmd As New SqlCommand(inputSqlString, conn)
Dim dataAdapter As New SqlDataAdapter(SqlCmd)
Dim fetchedDataSet As New DataSet
fetchedDataSet.Clear()
dataAdapter.Fill(fetchedDataSet)
Dim fetchedDataTable As DataTable = fetchedDataSet.Tables(0)
Return fetchedDataTable
Catch ex As Exception
MsgBox(Err.Description)
End Try
End Function
' this sub will update a table
Public Sub MyMethodUpdateTable(ByVal sqlString As String, ByVal tbToUpdate As DataTable)
Dim SqlCmd As New SqlCommand(sqlString, conn)
Dim dataAdapter As New SqlDataAdapter(SqlCmd)
Dim objCommandBuilder As New SqlClient.SqlCommandBuilder(dataAdapter)
dataAdapter.Update(tbToUpdate)
End Sub
Public Function MyMethodfindRecord(ByVal strSearckKey As String, ByVal tableName As String, ByVal strColumnName As String) As Boolean
Try
Dim searchSql As String = "SELECT * FROM " & tableName & " WHERE " & strColumnName & "='" & strSearckKey & "'"
'Dim searchString As String = txtCategoryCode.Text
' searchOwnerCmd.Parameters.Clear()
' searchOwnerCmd.Parameters.AddWithValue("a", "%" & search & "%")
Dim tempTb As DataTable
Dim myTbClass As myClassTableActivities = New myClassTableActivities()
tempTb = myTbClass.myFunctionFetchTbData(searchSql)
If tempTb.Rows.Count = 0 Then
Return False
Else
Return True
End If
Catch ex As Exception
MsgBox(Err.Description)
End Try
End Function
Public Function myFunctionFetchSearchTB(ByVal inputSqlString As String) As DataTable
Try
Dim SqlCmd As New SqlCommand(inputSqlString, conn)
Dim dataAdapter As New SqlDataAdapter(SqlCmd)
Dim fetchedDataSet As New DataSet
fetchedDataSet.Clear()
dataAdapter.Fill(fetchedDataSet)
Dim fetchedSearchTB As DataTable = fetchedDataSet.Tables(0)
Return fetchedSearchTB
Catch ex As Exception
MsgBox(Err.Description)
End Try
End Function
OK. If I understood correctly, you have a problem in retrieving Data [String] from a Database Table into a ComboBox of DropDownStyle [DropDownList].
How do you fill/populate your ComboBox with Data From Database Table ?
In this link, Microsoft docs state, that:
Use the SelectedIndex property to programmatically determine the index
of the item selected by the user from the DropDownList control. The
index can then be used to retrieve the selected item from the Items
collection of the control.
In much more plain English
You can never SET ComboBox.Text Value while in DropDownList by code, which you already knew by testing your code, but you need to use DisplayMember and ValueMember or SelectedIndex.
ComboBox1.SelectedIndex = ComboBox1.FindStringExact(Trim(tempTb.Rows(0).Item("it_discount_profile")))
Please consider populating your ComboBox Control from Database Table using (Key,Value) Dictionary collection, here is an example
Thank you guys for all the advice's. The only way it can be done is the way u said. I thought of putting the working code and some points for the benefit of all.
proposed,
ComboBox1.SelectedIndex = comboBox1.FindStringExact(Trim(tempTb.Rows(0).Item("it_discount_profile")))"
does not work when u bind the datatable to the combobox. The values should be added to the combo box in run time if the above "SelectedIndex" method to work. The code to add items to the combobox is as follows(myClassTableActivities is a class defined by myself and its shown above),
Private Sub filldisProfiles()
Dim sqlString As String = "SELECT discount_profile FROM tb_discount_profiles"
Dim tempTb As DataTable
Dim myTbClass As myClassTableActivities = New myClassTableActivities()
tempTb = myTbClass.myFunctionFetchTbData(sqlString)
Dim i As Integer = 0
For i = 0 To tempTb.Rows.Count - 1
cmbDisProfile.Items.Add(Trim(tempTb.Rows(i).Item("discount_profile")))
Next
End Sub
After adding we can use the following code to display the data on combobox (DropDownList).
Private Sub txtItCode_TextChanged(sender As Object, e As EventArgs) Handles txtItCode.TextChanged
Try
Dim sqlString As String = "SELECT * FROM tb_items where it_code='" & Trim(txtItCode.Text) & "'"
Dim tempTb As DataTable
Dim myTbClass As myClassTableActivities = New myClassTableActivities()
tempTb = myTbClass.myFunctionFetchTbData(sqlString)
If Len(txtItCode.Text) < 4 Then
cmdAdd.Enabled = False
cmdDelete.Enabled = False
cmdSave.Enabled = False
Else
If tempTb.Rows.Count > 0 Then
With tempTb
txtItName.Text = Trim(tempTb.Rows(0).Item("it_name"))
cmbDisProfile.SelectedIndex = cmbDisProfile.FindStringExact(Trim(tempTb.Rows(0).Item("it_discount_profile")))
cmbProfitProfile.SelectedIndex = cmbProfitProfile.FindStringExact(Trim(tempTb.Rows(0).Item("it_profit_profile")))
cmbItCategory.SelectedIndex = cmbItCategory.FindStringExact(Trim(tempTb.Rows(0).Item("it_category")))
cmbFinanCategory.SelectedIndex = cmbFinanCategory.FindStringExact((tempTb.Rows(0).Item("it_finance_category")))
End With
cmdAdd.Enabled = False
cmdDelete.Enabled = True
cmdSave.Enabled = True
Else
cmdAdd.Enabled = True
cmdDelete.Enabled = False
cmdSave.Enabled = False
txtItName.Text = ""
Call fillItCategories()
Call fillProProfile()
Call filldisProfiles()
Call fillFinCat()
End If
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try

datagridview Image Display vb.net MS Access

my code is to read the image file path in every row and display it in the datagridview "Image" Column.
.....
what's the problem with my code? please help me fix this.
UPDATE
this is the updated code but it displays nothing.
Dim dbdataset As New DataTable
Try
con.Open()
query = "Select * FROM [svfmemberlist]"
cmd = New OleDbCommand(query, con)
da.SelectCommand = cmd
da.Fill(dbdataset)
dgvSearch.RowTemplate.Height = 150
source.DataSource = dbdataset
dgvSearch.DataSource = source
Dim img As New DataGridViewImageColumn()
dgvSearch.Columns.Add(img)
img.HeaderText = "Image"
img.Name = "img"
img.ImageLayout = DataGridViewImageCellLayout.Zoom
dgvSearch.Columns("img").DataGridView.AutoGenerateColumns = False
dgvSearch.Columns("Name").AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
dgvSearch.Columns("img").Width = 150
For Each row As DataGridViewRow In dgvSearch.Rows
If Not row.Cells("imgPath").FormattedValue.ToString = Nothing Then
Dim str As String = row.Cells("imgPath").FormattedValue.ToString
Dim inImg As Image = Image.FromFile(str)
row.Cells("img").Value = inImg
Else
img.Image = Nothing
End If
Next
con.Close()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
The following example does not match how you are loading data and images but with a little effort will work within your current code.
I created two columns in the DataGridView via the IDE, one Text and one Image DataGridViewColumn.
The first line in form load sets ImageLayout, second line of code sets alignment to top-left for appearances. Next I set auto-size mode for all columns followed by setting the row height for each row.
Next (these lines are to load images from a folder one level below the app folder).
Setup the path to the images.
Add images using FileImageBytes function (which I would place into a separate class or code module but works just fine in your form).
Yes everything is hard-wired so it's easy to see how everything works.
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
CType(DataGridView1.Columns("PictureColumn"), DataGridViewImageColumn).ImageLayout = DataGridViewImageCellLayout.Normal
DataGridView1.Columns.Cast(Of DataGridViewColumn).Select(Function(col) col).ToList _
.ForEach(Sub(col) col.CellTemplate.Style.Alignment = DataGridViewContentAlignment.TopLeft)
DataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells
DataGridView1.RowTemplate.Height = 222
Dim imagePath As String = IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Images")
DataGridView1.Rows.Add(New Object() {"Car1", FileImageBytes(IO.Path.Combine(imagePath, "Car1.bmp"))})
DataGridView1.Rows.Add(New Object() {"Car2", FileImageBytes(IO.Path.Combine(imagePath, "Car2.jpg"))})
End Sub
Public Function FileImageBytes(ByVal FileName As String) As Byte()
Dim fileStream As IO.FileStream = New IO.FileStream(FileName, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read)
Dim byteArray(CInt(fileStream.Length - 1)) As Byte
fileStream.Read(byteArray, 0, CInt(fileStream.Length))
Return byteArray
End Function
End Class

How to get values from variable in a private sub or make public variable that does not lose value

I am planning to create a project in the near future about quizzes and now I am practising some codes and this is my problem. I have a variable inside a private sub Button_Click. All variables work fine but I can't access it in other Private sub Button3_Click because it was a private variable so I decided it to make them a public variable.
Then when I ran it, it's only shows the last item on my database and I get back my original code and all the data in the database are shown and I create an event from my radiobutton when I checked it's automatically INSERT a data into my table. So I need the variable label but I can't access it in my event.
Note: All my controls are add programmatically when the database has a data except for panel1, button2 and button3.
This is my original code:
'This is for adding controls like labels and radiobutton dependeng in a number of data from database
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Try
Dim conn As OleDbConnection = GetDBConnection()
Dim cmd As New OleDbCommand("SELECT * FROM tblEcobags ORDER BY N ASC", conn)
cmd.Prepare()
Dim dataReader As OleDbDataReader = cmd.ExecuteReader()
Do While dataReader.Read
Dim Cpanel As New Panel()
Dim count As Integer = Panel1.Controls.OfType(Of Panel)().ToList().Count
count = Panel1.Controls.OfType(Of Panel)().ToList().Count
Cpanel.Location = New Point(10, (25 * count) * 2.2)
Cpanel.Size = New Size(537, 51)
Cpanel.Name = "Cpanel" & (count + 1)
Cpanel.BackColor = Color.White
Panel1.Controls.Add(Cpanel)
Dim label As New Label()
count = Cpanel.Controls.OfType(Of Label)().ToList().Count
label.Location = New Point(10, (25 * count))
label.AutoSize = True
label.Name = "label_" & (count + 1)
label.Text = dataReader.Item("N") & "."
label.Font = New Font(label.Font.FontFamily, 10, FontStyle.Bold)
Cpanel.Controls.Add(label)
Dim lblQ As New Label()
count = Cpanel.Controls.OfType(Of TextBox)().ToList().Count
lblQ.Location = New System.Drawing.Point(40, 25 * count)
lblQ.AutoSize = True
lblQ.Name = "lblQ" & (count + 1)
lblQ.Text = dataReader.Item("ProductDes")
lblQ.Font = New Font(lblQ.Font.FontFamily, 11)
Cpanel.Controls.Add(lblQ)
Dim rbChoiceA As New RadioButton()
count = Cpanel.Controls.OfType(Of RadioButton)().ToList().Count
rbChoiceA.Location = New Point(40, 25)
rbChoiceA.AutoSize = True
rbChoiceA.Name = "rb" & (count + 1)
rbChoiceA.Text = dataReader.Item("Each")
rbChoiceA.Font = New Font(rbChoiceA.Font.FontFamily, 10)
AddHandler rbChoiceA.CheckedChanged, AddressOf rbChoiceA_Checked
Cpanel.Controls.Add(rbChoiceA)
Dim rbChoiceB As New RadioButton()
count = Cpanel.Controls.OfType(Of RadioButton)().ToList().Count
rbChoiceB.Location = New Point(200, 25)
rbChoiceB.AutoSize = True
rbChoiceB.Name = "rb" & (count + 1)
rbChoiceB.Text = dataReader.Item("PerDozen")
rbChoiceB.Font = New Font(rbChoiceB.Font.FontFamily, 10)
Cpanel.Controls.Add(rbChoiceB)
Loop
Button2.Enabled = False
conn.Dispose()
conn.Close()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
'this is an event that i can't access my "label" that I add programmatically
Private Sub rbChoiceA_CheckedChanged(ByVal sender As Object, ByVal e As EventArgs)
Try
Dim conn As OleDbConnection = GetDBConnection()
Dim cmd As New OleDbCommand("INSERT INTO tblSubmit(N)VALUES('" & must be label.text & "') ", conn)
cmd.ExecuteNonQuery()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
You can set Variable as static in database or Text file or SQL or in program
like string myvar = "static";
Sorry for my bad description but I got it worked now. I used to declare it outside from any function but my mistakes that I made is declaring variable with parenthesis, I don't know the difference between that so I need to know the one without parenthesis works.
This is my modified declaration so It must be accessible to any function
Dim label as Label()
I got error on my updating code inside an event for my button2_Click
label = new label() ' I got error here
But when I removed the parenthesis on my declaration, it works.
Dim label as label
so may I ask what's the difference between that, why the one I used is no work than below that was worked. Thanks in advance for the respose.

VB.Net : Writing SQL Table field into Link Label Parent Control

I have a bunch of link label controls stored in SQL. I have figured out how to pull them and create the link label but when I try to write the lnk.Parent Control I get "Unable to cast object of type 'system.string' to type 'system.windows.forms.control'. Is there a way to convert this?
Private Sub CreateLinkLabel(Lnk_DT As DataTable)
Try
For Each row As DataRow In Lnk_DT.Rows
lnk = New LinkLabel
lnk.Name = row("FLD_LnkName").ToString
lnk.Text = row("FLD_LnkName").ToString
lnk.Font = New Font("Sans Serif", 10, FontStyle.Bold)
lnk.Location = New Point(20, i)
lnk.Parent = row("FLD_LnkPanel")
lnk.Tag = row("Fld_LnkTag").ToString
lnk.AutoSize = True
AddHandler lnk.LinkClicked, AddressOf lnk_LinkClicked
i = i + 25
Next
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
try this:
For Each c As Control In Me.Controls
If TypeOf c Is Panel Then
If c.Name = row("FLD_LnkPanel") Then
lnk.Parent = c
End If
End If
The Parent property should be assigned to a Form object (or other container control) so I suppose that you should write lnk.Parent = Me but in any case the correct way to add controls to a container is through the Add method of the Controls control collection.
For example, to add the newly created label to the current form, you write this inside your loop
Me.Controls.Add(lnk)
Looking at your code it seems that the field row("FLD_LnkPanel") is the name of a Panel control on your form. If you want to add the created label to this panel then you should write
Private Sub CreateLinkLabel(Lnk_DT As DataTable)
Try
For Each row As DataRow In Lnk_DT.Rows
' Get the panel name '
Dim panelName = row("FLD_LnkPanel")
' Search the panel between the Form controls'
Dim panel = Me.Controls.OfType(Of Panel)
.FirstOrDefault(Function(x) x.Name = panelName)
' If you got it, then proceed with the label creation
if panel IsNot Nothing Then
lnk = New LinkLabel
lnk.Name = row("FLD_LnkName").ToString
lnk.Text = row("FLD_LnkName").ToString
lnk.Font = New Font("Sans Serif", 10, FontStyle.Bold)
lnk.Location = New Point(20, i)
' lnk.Parent = row("FLD_LnkPanel")'
lnk.Tag = row("Fld_LnkTag").ToString
lnk.AutoSize = True
AddHandler lnk.LinkClicked, AddressOf lnk_LinkClicked
i = i + 25
' Add the label to the panel child controls
panel.Controls.Add(lnk)
End If
Next
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Consider something like this:
Private Sub CreateUIControls(Lnk_DT As DataTable)
For Each row As DataRow In Lnk_DT.Rows
Dim isPanelNew As Boolean
Dim pnl As Panel = GetPanel(row, isPanelNew)
CreateLink(row, pnl)
If isPanelNew Then
pnl.Location = New Point(10, 20) ' whatever logic
End If
Next
End Sub
Private Function GetPanel(item As DataRow, ByRef isNew As Boolean) As Panel
isNew = False
Dim pnlItem As Panel = Nothing
Dim pnlName As String = item.Field(Of String)("FLD_LnkPanel")
' check if panel already exists on form.
Dim pnl As Panel = (From p In Controls.OfType(Of Panel)()
Where p.Name = pnlName
Select p).SingleOrDefault()
If pnl Is Nothing Then
pnlItem = New Panel
pnlItem.Width = 200 ' whatever logic
isNew = True
Else
pnlItem = pnl
End If
Return pnlItem
End Function
Private Sub CreateLink(item As DataRow, parentControl As Panel)
' get how many links are in the panel.
Dim linksCount = parentControl.Controls.OfType(Of LinkLabel).Count()
Dim lnk As New LinkLabel
With lnk
.Name = item.Field(Of String)("FLD_LnkName")
.Text = item.Field(Of String)("FLD_LnkName")
.Font = New Font("Sans Serif", 10, FontStyle.Bold)
.Tag = item.Field(Of String)("Fld_LnkTag")
.AutoSize = True
' increase panel height to fit the new link.
parentControl.Height = ((linksCount + 1) * 25) + 10
.Parent = parentControl
.Location = New Point(20, (linksCount * 25) + 3)
AddHandler .LinkClicked, AddressOf lnk_LinkClicked
End With
End Sub

Buttons Added to FlowLayoutPanel pile up on top of each other

I'm using VS 2012 (vb.net) and I have a form with a flowLayoutPanel which is meant to contain an unknown number of buttons. To make it simple, basically, when the form Loads I fetch items from a table based one some criteria and then a use a For...Next block to add a button for each item to the flowLayoutPanel. So if I find 5 items I add 5 buttons all named differently but the problem is that they seem to pile up on each other instead of lining up nicely. When I use a button to add the items one after the other it works fine but when I use the For...Next block it does not work. I have tried refreshing the flowLayoutPanel after adding each button, I have tried to set the location of each new button relative to the location of the previous button but it still does to work.
I have researched this for over a week now and there is a ton of stuff out there but nothing specifically deals with this.
Thanks for your help.
This is the relevant part of my code:
`Try
If conn.State <> ConnectionState.Open Then
conn.Open()
End If
sql = "SELECT ItemCode, Description, NormalPrice FROM items WHERE items.Class = 'ICE CREAM'"
cmd = New MySqlCommand(sql, conn)
da.SelectCommand = cmd
'fill dataset
da.Fill(ds, "items")
rowscount = ds.Tables("items").Rows.Count
If rowscount > 0 Then 'there are records so go ahead
Dim ID As Integer
Dim desc As String
Dim newbutton As New Button
Dim newCode As New TextBox
For i As Integer = 0 To rowscount - 1
ID = ds.Tables("items").Rows(i).Item("ItemCode")
desc = ds.Tables("items").Rows(i).Item("Description")
newCode.Name = "mnuCode" & i
newCode.Text = ID
newCode.Visible = False
Me.Controls.Add(newCode)
newbutton.Name = "mnuButton" & i
newbutton.Text = desc
newbutton.Size = New Size(150, 100)
newbutton.BackColor = Color.Orange
newbutton.ForeColor = Color.White
newbutton.Font = New Font("Arial", 16, FontStyle.Bold)
newbutton.TextAlign = ContentAlignment.MiddleCenter
newbutton.Text = Regex.Unescape(desc)
newbutton.Top = (150 + (i * 100))
fPanel.Refresh()
AddHandler newbutton.Click, AddressOf ButtonClicked
fPanel.Controls.Add(newbutton)
Next
End If
ds.Reset()
conn.Close()
Catch ex As MySqlException
Finally
conn.Dispose()
End Try`
You are not creating multiple buttons. You just keep changing the properties on the same button over and over again. Since Button is a reference type, you need to call New each time you need a new object instance
For instance, instead of this:
Dim newbutton As New Button
For i As Integer = 0 To rowscount - 1
' ...
fPanel.Controls.Add(newbutton)
Next
Do this:
For i As Integer = 0 To rowscount - 1
Dim newbutton As New Button
' ...
fPanel.Controls.Add(newbutton)
Next
Or:
Dim newbutton As Button = Nothing
For i As Integer = 0 To rowscount - 1
newbutton = New Button
' ...
fPanel.Controls.Add(newbutton)
Next