change the text of buttons from database (list of string) - vb.net

I'm new to vb.net so I'm seeking for help,
I have method to create buttons in panel layout, and what I want is to set the TEXT for each button from database table ( but the customer TEXT ),
so how can I do it?
this is the method to generate buttons:
Private Sub GenerateTable(columnCount As Integer, rowCount As Integer)
'Clear out the existing controls, we are generating a new table layout
TableLayoutPanel1.Controls.Clear()
'Clear out the existing row and column styles
TableLayoutPanel1.ColumnStyles.Clear()
TableLayoutPanel1.RowStyles.Clear()
'Now we will generate the table, setting up the row and column counts first
TableLayoutPanel1.ColumnCount = columnCount
TableLayoutPanel1.RowCount = rowCount
For x As Integer = 0 To columnCount - 1
'First add a column
TableLayoutPanel1.ColumnStyles.Add(New ColumnStyle(SizeType.AutoSize))
For y As Integer = 0 To rowCount - 1
'Next, add a row. Only do this when once, when creating the first column
If x = 0 Then
TableLayoutPanel1.RowStyles.Add(New RowStyle(SizeType.AutoSize))
End If
'Create the control, in this case we will add a button
Dim cmd As New Button()
cmd.Width = 200
cmd.Height = 40
Dim count As Integer = TableLayoutPanel1.Controls.OfType(Of Button)().ToList().Count
fill_combobox
cmd.Name = "button_" & (count + 1)
cmd.Text = "button_" & (count + 1)
AddHandler cmd.Click, AddressOf Button_Click
Panel1.Controls.Add(cmd)
'cmd.Text = String.Format("({0}, {1})", x, y)
'Finally, add the control to the correct location in the table
TableLayoutPanel1.Controls.Add(cmd, x, y)
Next
Next
End Sub
this is how to call all customers TEXT or id as list of strings from database :
Dim myList As New List(Of String)()
Private Sub fill_combobox()
Try
If SQL.conn.State = ConnectionState.Open Then
SQL.conn.Close()
End If
SQL.conn.Open()
Dim cmd As New SqlCommand()
cmd.Connection = SQL.conn
cmd.CommandText = "SELECT cust_id FROM customers order by date"
Dim dr As SqlDataReader = cmd.ExecuteReader
While dr.Read
Dim esection As String = dr.Item(0)
myList.Add(String.Format(esection))
End While
dr.Close()
SQL.conn.Close()
Catch ex As SqlException
MsgBox(ex.Message, MsgBoxStyle.Critical, "SQL Error")
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical, "General Error")
End Try
End Sub

Im elaborating on Subazs' comment. It could be easier to create a collection or List(of Button) then add all of your buttons into this as you itterate them into the flowtable. You can then call back to these at a later date, they will be stored in the list until you dispose of the form. NOTE they are with the form if you code it like this.
I have altered your code slightly too, you must remember to dispose the cmd as well as closing the connection (I had an awful experience not doing this which cost me!)
Dim myList As New List(Of String)
Dim myButtons As List(Of Button)
Public Sub Run_Me()
Retrieve_Customers()
'You can change the 5 and it will change the layout panel for you... :)
GenerateTable_and_Buttons(5)
MsgBox("All done!")
End Sub
'Replaces your (Fill_Combo_Box) method
Private Sub Retrieve_Customers()
Try
myList = New List(Of String)
If Sql.conn.State = ConnectionState.Open Then Sql.conn.Close()
Sql.conn.Open()
'Do you want to add in the customer name instead of ID? - if so we can change here...
Dim qry As String = "SELECT cust_id FROM customers order by date"
Dim cmd As New SqlCommand(qry, Sql.conn)
Dim dr As SqlDataReader = cmd.ExecuteReader
While dr.Read
Dim s As String = dr.Item(0)
myList.Add(String.Format(s))
End While
dr.Close()
cmd.Dispose()
Sql.conn.Close()
Catch ex As SqlException
MsgBox(ex.Message, MsgBoxStyle.Critical, "SQL Error")
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical, "General Error")
End Try
'Now we have built a list of the customer - myList we can go on to count these...
End Sub
Private Sub GenerateTable_and_Buttons(columnCount As Integer)
If myList Is Nothing Then Exit Sub 'Just exit if we have no customers?
myButtons = New List(Of Button)
'This will round UP to make sure we have enough rows - also can do something like +1 on end if want extra?
Dim rowCount As Integer = CInt(Math.Round(Math.Ceiling(myList.Count / columnCount), 0))
Dim tlp As TableLayoutPanel = Me.TableLayoutPanel1
'Clear out the existing controls, we are generating a new table layout
tlp.Controls.Clear()
'Clear out the existing row and column styles
tlp.ColumnStyles.Clear()
tlp.RowStyles.Clear()
'Now we will generate the table, setting up the row and column counts first
tlp.ColumnCount = columnCount
tlp.RowCount = rowCount
Dim count As Integer = 0
For x As Integer = 0 To columnCount - 1
'First add a column
tlp.ColumnStyles.Add(New ColumnStyle(SizeType.AutoSize))
For y As Integer = 0 To rowCount - 1
'Next, add a row. Only do this when once, when creating the first column
If x = 0 Then
tlp.RowStyles.Add(New RowStyle(SizeType.AutoSize))
End If
'Create the control, in this case we will add a button
Dim cmd As New Button
cmd.Width = 200
cmd.Height = 40
'<<Add the customer ID into the TAG of the control, the tag is great place to store things
'We can then access the tag in another method, ie if we want to open it using your Button_Click
'method. We can say :
'Dim CustID As String = sender.Tag
'Then we can do other things with the ID....>>
If mylist.count > count then
cmd.Tag = myList(count)
cmd.Text = myList(count)
end if
'fill_combobox() ' I dont know why this is here?
cmd.Name = "button_" & (count + 1)
cmd.Text = "button_" & (count + 1)
AddHandler cmd.Click, AddressOf Button_Click
myButtons.Add(cmd)
'<<<<<<<<<<<<<<<<<
Panel1.Controls.Add(cmd) '<<<<<<<<< Whats Panel1????
'>>>>>>>>>>>>>>>>>>
'Finally, add the control to the correct location in the table
tlp.Controls.Add(cmd, x, y)
count += 1
Next
Next
End Sub

Related

Empty lines appears in datagridview

When I go to add data in first row there is empty lines that appear below my code, why do these lines appear? I need only to add data in one row and save it.
Dim pringdata As String = "SELECT * FROM itemInfo "
Dim sqlconload As New SqlConnection(sqlcon)
Try
sqlconload.Open()
Dim da As New SqlDataAdapter(pringdata, sqlconload)
ds.Clear()
da.Fill(ds, "itemInfo")
Dim rowcount As Integer
rowcount = ds.Tables("itemInfo").Rows.Count
If rowcount >= 1 Then
DGVorders.Rows.Add(rowcount)
For i = 0 To rowcount - 1
If DGVorders.CurrentRow.Cells(0).Value = ds.Tables("itemInfo").Rows(i).Item("itemCode") Then
DGVorders(1, e.RowIndex).Value = ds.Tables("itemInfo").Rows(i).Item("itemName")
DGVorders(2, e.RowIndex).Value = ds.Tables("itemInfo").Rows(i).Item("Uint1")
DGVorders(4, e.RowIndex).Value = ds.Tables("itemInfo").Rows(i).Item("price1")
End If
Next
End If
sqlconload.Close()
Catch ex As Exception
End Try
End Sub
Modify the "AllowUsersToAddRows" property to remove that blank line.
Example:
DataGridView1.AllowUserToAddRows = False
DGVorders.Rows.Add(rowcount) will add rowcount amount of empty rows to your DataGridView. I don't know why you are doing that, it's not as if you are adding values to the cells in those new rows in your for loop.
updated
If dataGridView1.CurrentRow.Cells(0).Value = ds.Tables("itemInfo").Rows(i)("itemCode") Then
Dim newRow As DataGridViewRow = TryCast(dataGridView1.CurrentRow.Clone(), DataGridViewRow)
newRow.Cells(1).Value = ds.Tables("itemInfo").Rows(i)("itemName")
newRow.Cells(2).Value = ds.Tables("itemInfo").Rows(i)("Uint1")
newRow.Cells(3).Value = ds.Tables("itemInfo").Rows(i)("price1")
dataGridView1.Rows.Add(newRow)
End If

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

Deleting multiple records from sql bound Datagrid

The procedures below allowed me to delete several records at once by checking the checkbox on my datagrid. The procedure was written on ASP.net but now I am using a winform on VB.net.
I have a datagrid with column name "Delete" where the checkboxes are located. The user would check
the records it wants to delete and the would delete those records. I use the "Ticket Number" column values as the parameter for my query.
The issue I have is that since was written for ASP.Net, I cannot find how the winform VB.net equivalent for this line:
Dim chkDelete As CheckBox = DirectCast(grdRoster.Rows(i).Cells(0).FindControl("Delete_Row"), CheckBox)
FindControl is not a member of System.Windows.Forms.DataGridViewCell. Plus I am pretty sure that the whole line is wrong since the checkboxes
are located on a datagrid column set as ColumnType: DataGridViewCheckBoxColumn and are not really individual controls.
How can I get the same result on a winform? Here is my entire code.
Private Sub btnDelete_Click(sender As Object, e As EventArgs) Handles btnDelete.Click
'Create String Collection to store
'IDs of records to be deleted
Dim ticketNumberCollection As New StringCollection()
Dim strTicketNumber As String = String.Empty
'Loop through GridView rows to find checked rows
For i As Integer = 0 To grdRoster.Rows.Count - 1
Dim chkDelete As CheckBox = DirectCast(grdRoster.Rows(i).Cells(0).FindControl("Delete_Row"), CheckBox)
If chkDelete IsNot Nothing Then
If chkDelete.Checked Then
strTicketNumber = grdRoster.Rows(i).Cells(1).ToString
ticketNumberCollection.Add(strTicketNumber)
End If
End If
Next
'Call the method to Delete records
DeleteMultipleRecords(ticketNumberCollection)
' rebind the GridView
grdRoster.DataBind()
End Sub
' Sub to delete multiple records
' #param "idCollection" calls the string collection above
' and deletes the selected record separated by ","
Private Sub DeleteMultipleRecords(ByVal ticketNumberCollection As StringCollection)
Dim IDs As String = ""
'Create string builder to store
'delete commands separated by ,
For Each id As String In ticketNumberCollection
IDs += id.ToString() & ","
Next
Try
Dim strTicketID As String = IDs.Substring(0, IDs.LastIndexOf(","))
DataSheetTableAdapter.DeleteRecord(strTicketID)
Catch ex As Exception
Dim errorMsg As String = "Error in Deletion"
errorMsg += ex.Message
Throw New Exception(errorMsg)
Finally
Me.Close()
End Try
End Sub
for deleting multiple records from a data bound gridview you should create the DataGridViewCheckBoxColumn at run time
Dim chk As New DataGridViewCheckBoxColumn()
DataGridView1.Columns.Add(chk)
chk.HeaderText = "Select"
'then bind your datagridview with dataset
Dim sql As String = "SELECT * FROM table_name"
' Dim connection As New SqlConnection(connectionString)
conn.Open()
sCommand = New SqlCommand(sql, conn)
sAdapter = New SqlDataAdapter(sCommand)
sBuilder = New SqlCommandBuilder(sAdapter)
sDs = New DataSet()
sAdapter.Fill(sDs, "table_name")
sTable = sDs.Tables("table_name")
DataGridView1.DataSource = sDs.Tables("table_name")
'then traverse through each column and get the checked values
Try
DataGridView1.EndEdit()
For j = Me.DataGridView1.Rows.Count - 1 To 0 Step -1
If Not IsDBNull(DataGridView1.Rows(j).Cells(0).Value) Then
If DataGridView1.Rows(j).Cells(0).Value = True Then
check = True
If MessageBox.Show("Do you want to delete these records?", "Delete", MessageBoxButtons.YesNo) = DialogResult.Yes Then
For i = Me.DataGridView1.Rows.Count - 1 To 0 Step -1
If Not IsDBNull(DataGridView1.Rows(i).Cells(0).Value) Then
If DataGridView1.Rows(i).Cells(0).Value = True Then
'remove the checked columns and update datatable
DataGridView1.Rows.RemoveAt(i)
sAdapter.Update(sTable)
End If
End If
Next
Else
Return
End If
Else
End If
End If
Next
If check = False Then
MsgBox("Nothing Selected")
End If
Catch ex As Exception
MsgBox(ex.ToString)
End Try

Getting Info out of a DataGridView

I need to get the information that is in each cell located in the datagrid view of the rows that the user selects. I have the selecting rows down, I just need help with getting the information in the cell. Right now it just returns as DataGridVewRow { Index=7} when the data is really a string. Here is my function
Private Function getCoordinates()
Dim dt As New DataTable
Dim dt2 As New DataTable
'Dim r As DataRow
Dim n As Integer = 0
Dim selectedItems As DataGridViewSelectedRowCollection = dgv.SelectedRows
dt = dgv.DataSource
dgv.SelectionMode = DataGridViewSelectionMode.FullRowSelect
dgv.MultiSelect = True
Dim i = dgv.CurrentRow.Index
dt2.Columns.Add("Position")
Try
If selectedItems Is Nothing Then
For n = 0 To dt.Rows.Count - 1
dt2.Rows.Add(n)
dt2.Rows(n)("Position") = dt.Rows.Item(n)("Mouse Position")
Next
Else
For Each selectedItem As DataGridViewRow In selectedItems
dt2.Rows.Add(selectedItem)
dt2.Rows(selectedItem.Index)("Position") = dt.Rows.Item(selectedItem.Index)("Mouse Position")
Next
End If
Catch ex As Exception
MsgBox("Error", MsgBoxStyle.Exclamation, "Error!")
End Try
Return dt2
End Function
You get the text of the cells via the DataGridViewRow's Cells property. The following example would get the text from the first cell in each selected row:
Dim strContents As String = String.Empty
For Each selectedItem As DataGridViewRow In selectedItems
strContents += " First Cell's Text: " & selectedItem.Cells(0).Text
Next

Converting Gridview to DataTable in VB.NET

I am using this function to create datatable from gridviews. It works fine with Gridviews with AutoGenerateColumns = False and have boundfields or template fileds. But if I use it with Gridviews with AutoGenerateColumn = True I only get back an empty DataTable. Seems Gridview viewstate has been lost or something. Gridview is binded on PageLoad with If Not IsPostback. I can't think of anything else to make it work. Hope someone can help me.
Thanks,
Public Shared Function GridviewToDataTable(gv As GridView) As DataTable
Dim dt As New DataTable
For Each col As DataControlField In gv.Columns
dt.Columns.Add(col.HeaderText)
Next
For Each row As GridViewRow In gv.Rows
Dim nrow As DataRow = dt.NewRow
Dim z As Integer = 0
For Each col As DataControlField In gv.Columns
nrow(z) = row.Cells(z).Text.Replace(" ", "")
z += 1
Next
dt.Rows.Add(nrow)
Next
Return dt
End Function
Slight modification to your function above. If the autogenerate delete, edit or select button flags are set, the values for the fields are offset by one. The following code accounts for that:
Public Shared Function GridviewToDataTable(ByVal PassedGridView As GridView, ByRef Error_Message As String) As DataTable
'-----------------------------------------------
'Dim Tbl_StackSheets = New Data.DataTable
'Tbl_StackSheets = ReportsCommonClass.GridviewToDataTable(StackSheetsGridView)
'-----------------------------------------------
Dim dt As New DataTable
Dim ColInd As Integer = 0
Dim ValOffset As Integer
Try
For Each col As DataControlField In PassedGridView.Columns
dt.Columns.Add(col.HeaderText)
Next
If (PassedGridView.AutoGenerateDeleteButton Or PassedGridView.AutoGenerateEditButton Or PassedGridView.AutoGenerateSelectButton) Then
ValOffset = 1
Else
ValOffset = 0
End If
For Each row As GridViewRow In PassedGridView.Rows
Dim NewDataRow As DataRow = dt.NewRow
ColInd = 0
For Each col As DataControlField In PassedGridView.Columns
NewDataRow(ColInd) = row.Cells(ColInd + ValOffset).Text.Replace(" ", "")
ColInd += 1
Next
dt.Rows.Add(NewDataRow)
Next
Error_Message = Nothing
Catch ex As Exception
Error_Message = "GridviewToDataTable: " & ex.Message
End Try
Return dt
End Function