How to control combo box values in vb.net 2010 - mysql

Hello to all I am new here and also new to VB.NET. I want to control my combo box values to show all names from MySQL database. When I select name from combo box, I want to set the textbox text.
Private Sub fnames()
Try
Dim reader As MySqlDataReader
dbcon.Open()
Dim kweri2 As String = "select * from customer order by lname"
mysqlcmd = New MySqlCommand(kweri2, dbcon)
reader = mysqlcmd.ExecuteReader
While reader.Read
search_cmb.Items.Add(reader.GetString("lname"))
search_cmb.ValueMember = reader.GetString("customer_id")
End While
dbcon.Close()
Catch ex As Exception
MsgBox("Error: " & ex.Message)
Finally
dbcon.Dispose()
End Try
End Sub
then i called the fname() function on load and then:
Private Sub search_cmb_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles search_cmb.SelectedIndexChanged
costumerid_txt.Text = search_cmb.ValueMember.ToString()
End Sub
This code, however, does not work properly. It only shows all lnames but when I select one it will set the string "2" on the textbox which is 2nd id from database and it is not changing even when I choose a different option in the combo box.
Any help would be appreciated.

You are completely misusing the ValueMember property. The ValueMember is the member from which the value is drawn, not the value itself. It is only relevant when using data-binding, so use data-binding. You bind a list of items to the control, set the DisplayMember to the name of column/property from which to draw the text to be displayed and set the ValueMember to the name of the column/property from which to draw the corresponding value.
Don't use a data reader but rather a data adapter. Call Fill on it to populate a DataTable and then bind that to the control:
search_cmb.DisplayMember = "lname"
search_cmb.ValueMember = "customer_id"
search_cmb.DataSource = myDataTable
When the user makes a selection, you then get the value for the selected item from the SelectedValue property:
costumerid_txt.Text = search_cmb.SelectedValue.ToString()
That said, you don't need any code to transfer data from the ComboBox to the TextBox. Just bind the TextBox to the same DataTable and it will happen automatically:
search_cmb.DisplayMember = "lname"
search_cmb.DataSource = myDataTable
costumerid_txt.DataBindings.Add("Text", myDataTable, "customer_id")
I'd probably also recommend binding the DataTable to a BindingSource first and then binding that to the controls if you intend to make changes and save them.

Related

Is there a way to display a ComboBox's DisplayMember value gathered from a MySQL database into a datagridview cell?

So I am trying to create a POS system where the app fetches the inventory from a database, puts all the value into a ComboBox and uses a DataGridView for the cart. My only problem is that the DataGridView Cell doesn't display the value of DisplayMember Properly.
My fetch code looks like this, and it runs at form runtime, or when manually refreshed.
Using connect As MySqlConnection = New MySqlConnection(connectStr)
Using sda As MySqlDataAdapter = New MySqlDataAdapter("SELECT Item, Price FROM Storeinventory", connect)
'Fill the DataTable with records from Table.
Dim dt As DataTable = New DataTable()
sda.Fill(dt)
'Assign DataTable as DataSource.
cart1.DataSource = dt
cart1.DisplayMember = "Item"
cart1.ValueMember = "Price"
cart1Price.Text = " " & cart1.SelectedValue
End Using
And with this, the name of the Product shows up properly in the combobox.
However, when adding the value of displaymember into a datagridview, it only shows up as "Item" instead of the actual product name, i.e. "Doom" but the price value is fine.
This is my main activity window:
And this is what happens when I add it:
The Price displays fine but name doesn't.
And here's my bit of code that adds the item into the datagridview:
Private Sub AddCart_Click(sender As Object, e As EventArgs) Handles AddCart.Click
Dim dm As String
Dim vm As String
Dim qt As String
dm = cart1.DisplayMember
vm = cart1.SelectedValue
qt = cart1Quantity.Text
Row = {dm, vm, qt}
DataGridView1.Rows.Add(Row)
End Sub

Populating text boxes via Combobox and SQL database table

I am trying to populate a set of textboxes from a combobox on a form. The combo box is populated using a dataset when the form loads. When this is loaded it needs to show only one entry per unit number in the kitcombobox (which is a unit number for a kit with multiple pieces of equipment in it) but display the multiple pieces of equipment's information in the different text boxes when the unit number is selected via the kitcombobox. What approach should I take towards this? I'm really lost and this is all I have so far :(
Private Sub ckunit()
Dim ds As New DataSet
Dim cs As String = My.Settings.MacroQualityConnectionString
Dim kitcombobox As String = "SELECT DISTINCT Unit_Number, Status FROM Calibrated_Equipment WHERE CHARINDEX('CK', Unit_Number) > 0 AND Status='" & ckstatuscombbx.Text & "'"
Dim sqlconnect As New SqlConnection(cs)
Dim da As New SqlDataAdapter(kitcombobox, sqlconnect)
sqlconnect.Open()
da.Fill(ds, "Calibrated_Equipment")
sqlconnect.Close()
kitcombbx.DataSource = ds.Tables(0)
End Sub
Assuming you are using WinForms, I think the key will be adding an event handler for the SelectionChangedCommitted event on kitcombbx.
You can then checked the properties on the combobox to check what is selected and run another query to pull equipment information for that kit. It'd probably look something like this:
Private Sub kitcombbx_SelectionChangeCommitted(sender As Object, e As EventArgs) _
Handles kitcombbx.SelectionChangeCommitted
Dim kit = kitcombbx.SelectedItem.ToString()
Dim kitEquipment = FetchKitEquipmentInformation(kit)
PopulateEquipmentInformation(kitEquipment)
End Sub
The way you're currently constructing your query (by concatenating string parameters directly from user input) results in bad performance for most database systems, and moreover, is a huge security vulnerability. Look up SQL injection for more detail (or read these two questions).
Better DB code would probably look something like this:
Dim query = New StringBuilder()
query.AppendLine("SELECT DISTINCT Unit_Number, Status ")
query.AppendLine("FROM Calibrated_Equipment ")
query.AppendLine("WHERE CHARINDEX('CK', Unit_Number) > 0 ")
query.AppendLine(" AND Status = #STATUS ")
Dim connection As New SqlConnection(My.Settings.MacroQualityConnectionString)
Dim command As New SqlCommand(query, connection);
command.Parameters.Add("#STATUS", ckstatuscombbx.Text);
Dim da As New SqlDataAdapter(kitcombobox, sqlconnect)
'And so on...
Your question is a bit broad (and therefore, likely off-topic for StackOverflow), see How to Ask.

Displaying database record on a label in VB.Net

I have this problem that when I put id no. in the textbox1 and click the button1 the record successfully shows, but when I change the id no. in the textbox1 and click button1 again the error says
ArgumentException was unhandled
This causes two bindings in the collection to bind to the same property. Parameter name: binding
I really don't understand the meaning of this, by the way still new and getting used to vb.net
Imports MySql.Data.MySqlClient
Public Class Form16
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim thisConnection As New MySqlConnection("server=localhost;user id=root;database=db")
Dim DataSet1 As New DataSet
Dim sql As String = "SELECT * FROM voter where vid='" & TextBox1.Text & "'"
Dim da As New MySqlDataAdapter(sql, thisConnection)
da.Fill(DataSet1, "db")
Label2.DataBindings.Add("text", DataSet1, "db.fname")
Label10.DataBindings.Add("text", DataSet1, "db.mi")
Label11.DataBindings.Add("text", DataSet1, "db.lname")
Label12.DataBindings.Add("text", DataSet1, "db.yr")
Label13.DataBindings.Add("text", DataSet1, "db.sec")
Label14.DataBindings.Add("text", DataSet1, "db.vstatus")
End Sub
End Class
If you don't clear the DataBindings collection before rebinding, this error will be thrown because a control can only have one binding to a specified property.
For instance, Label2 can only have one binding to the property Text. But when you're clicking the button for the second time the binding added in the first click is still in the collection.
First click:
Label2.DataBindings.Add("Text", DataSet1, "db.fname")
Second click:
'Will throw an error because there's already a binding to property `Text`:
Label2.DataBindings.Add("Text", DataSet1, "db.fname")
Before you add a new binding, be sure the binding doesn't already exists.
'Always do a reversed loop when removing items from a collection.
For index As Integer = (Label2.DataBindings.Count - 1) To 0 Step -1
If (Label2.DataBindings.Item(index).PropertyName = "Text") Then
'Ops, a binding to the property `Text` already exists.
'Remove this and we'll be fine.
Label2.DataBindings.RemoveAt(index)
End If
Next
'We can now safely add a new binding to the `Text` property.
Label2.DataBindings.Add("Text", DataSet1, "db.fname")
A more simpler way is to just clear the collection.
Label2.DataBindings.Clear()
Label2.DataBindings.Add("Text", DataSet1, "db.fname")

Populate a textbox with mysql data after a combobox selection

So I have 2 mysql tables, one called "Service_Details" and one called "Payment_details"
I have a combobox in my form which displays the "service_id" field from the service table.
I'm trying to code a textbox, so when I select the service id from the combobox it writes the "service" which is another field in my service details table. The service id is linked to a service.
I am getting errors 'identifier expected' at [0] and 'Value of type 'system.data.datatablecollection' cannot be converted to 'string' at dss.tables
I can't seem to get it working after browsing the internet for an hour
Here is my code:
Private Sub cbxserviceid_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cbxserviceid.SelectedIndexChanged
Dim dss As New DataSet
Dim daa As New MySqlDataAdapter("SELECT * from service_details WHERE ServiceID='" + cbxserviceid.Text + "'", objconnection)
Dim cmddd = New MySqlCommandBuilder(daa)
daa.Fill(dss)
txtService1.Text = dss.Tables[0].Rows[0]["Service"].ToString();
End Sub
The indexes in VB.NET are expressed using the round braces, the square brackets are used in C#
txtService1.Text = dss.Tables(0).Rows(0)("Service").ToString()
Also avoid to use string concatenation for sql command texts, use always a parameterized query
Private Sub cbxserviceid_SelectedIndexChanged(......)
Dim dss As New DataSet
if cbxserviceid.SelectedIndex <> -1 Then
Dim daa As New MySqlDataAdapter("SELECT * from service_details WHERE ServiceID=#id", _
objconnection)
daa.SelectCommand.Parameters.AddWithValue("#id", Convert.ToInt32(cbxserviceid.Text))
daa.Fill(dss)
txtService1.Text = dss.Tables(0).Rows(0)("Service").ToString()
End If
End Sub
I have also removed the creation of the MySqlCommandBuilder, being the adapter a local variable it has no sense or effect (if this is all your code in this event of course).
Looking at the comments below and the chat with the poster there is also another error to fix.
When assign a DataSource, DisplayMember and ValueMember property of a combobox it is mandatory to follow a precise order to avoid unwanted side effects
cbxserviceid.DisplayMember = "ServiceID"
cbxserviceid.ValueMember = "ServiceID"
cbxserviceid.DataSource = datatable

LINQ to SQL datagridview query returns length, not value

I've got a Windows Form with a button and a datagridview. The project includes a working database connection and LINQ to SQL class. I'm trying to bind the datagridview to the LINQ to SQL.
In a code module I've got this:
Public Function DataGridList() As BindingSource
Dim NewBindingSource As New BindingSource()
Dim db As New DataClasses1DataContext()
NewBindingSource.DataSource = _
From Block In db.BLOCK_ASSIGNMENTs
Where Block.gr912_school = "Franklin"
Select Block.gr6_school Distinct
Return NewBindingSource
End Function
And this button_click code in the form:
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
DataGridView1.DataSource = DataGridList()
End Sub
When I click the button I get the length of the school names in the datagridview, with a column header of "length."
If I just run this very similar code in the button_click instead, the school names appear correctly in the immediate window:
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim db As New DataClasses1DataContext()
Dim TestQuery =
From Block In db.BLOCK_ASSIGNMENTs
Where Block.gr912_school = "Franklin"
Select Block.gr6_school Distinct
For Each block In TestQuery
Debug.Print(block)
Next
End Sub
Give this a try:
Public Function DataGridList() As BindingSource
Dim NewBindingSource As New BindingSource()
Dim db As New DataClasses1DataContext()
NewBindingSource.DataSource = _
From Block In db.BLOCK_ASSIGNMENTs
Where Block.gr912_school = "Franklin"
Select New With { Key .Value = Block.gr6_school } Distinct
Return NewBindingSource
End Function
This should give it a property that the DataGridView can pick up on. The New With... creates an anonymous object with a Property named Value. The DataGridView works on this type of object by enumerating the public properties and rendering them as columns. If you had needed more than one value, you could have added additional items inside the curly braces in the same way separated by commas. See Anonymous Types (Visual Basic) for more information.
You might try adding a .ToString to the Select:
From Block In db.BLOCK_ASSIGNMENTs
Where Block.gr912_school = "Franklin"
Select Block.gr6_school.ToString Distinct
I believe that Debug.Print does an implicit conversion to .ToString when it prints to the immediate window. However, a datagrid cell treats everything as an object and displays the default property for that object.
Turns out, of course, this has been addressed often, including on SO, and here. The route I chose was to use an intermediate DataTable:
Public Function DataGridList() As DataTable
Dim NewDataTable As New DataTable
Dim db As New DataClasses1DataContext()
Dim i As Int32
Dim qry =
From Block In db.BLOCK_ASSIGNMENTs.AsEnumerable
Where Block.gr912_school = "Franklin"
Select Block.gr6_school Distinct
NewDataTable.Columns.Add("School")
For i = 0 To qry.Count - 1
NewDataTable.Rows.Add(qry(i))
Next
Return NewDataTable
End Function
This seems pretty slow the first time it runs, so I may try something else in the future, but it allows me to feed the grid via LINQ, which is what I want to work with.
(I would like to use the qry's CopyToDataTable property, but it's only available if the query returns a DataTableRows collection, or some such, and my hacking around didn't reveal how to do that.)