Reputation: 1753
I am using a while loop to populate a second combo based on the value of the first combobox selection. What is happening however, is that the loop is only displaying 1 item in the second combobox instead of about 20. If I set breakpoint on the while loop I can see that all items are being calculated but just not appearing in the combobox.
I would be grateful if someone could point my basic newbie error. Many thanks
Private Sub cmbCustomer_SelectedIndexChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles cmbCustomer.SelectedIndexChanged
sql = "SELECT * from Departments WHERE Customer = '" & cmbCustomer.Text & "'"
Dim cmd As New OleDb.OleDbCommand
cmd.CommandText = sql
cmd.Connection = oledbCnn
dr = cmd.ExecuteReader
While dr.Read()
If (dr.HasRows) Then
cmbDept.Text = CStr((dr("Name"))) <--- 2nd combobox
End If
End While
cmd.Dispose()
dr.Close()
End Sub
Upvotes: 0
Views: 221
Reputation: 112352
The Text
property of the combo box contains only what is displayed for the selected item. You need to add the items to the Items
collection:
cmbDept.Items.Add(CStr(dr("Name")))
The combo boxes, list boxes etc. display items by calling their ToString()
method. Therefore calling CStr
should not even be necessary:
cmbDept.Items.Add(dr("Name"))
You are inserting a value in the SQL statement by concatenating strings. If you are just using your program for yourself, this is okay; however, on productive environments this is dangerous. Someone could enter a value that terminates the SELECT statement and introduces another malicious statement. E.g. a DELETE statement that deletes a whole table. This is called a SQL injection attack.
There are two ways to deal with this:
1) Escape the string:
sql = "SELECT * FROM Dep WHERE Cust = '" & s.Replace("'", "''") & "'"
2) Use command parameters:
sql = "SELECT * from Departments WHERE Customer = ?"
Dim cmd As New OleDbCommand(sql, oledbCnn)
cmd.Parameters.AddWithValue("@p1", cmbCustomer.Text)
If you are inserting dates this also has the advantage that you don't need to bother about date formats.
You can simplify your loop to:
While dr.Read()
cmbDept.Text = CStr(dr("Name"))
End While
There is no need to test for HasRows
since dr.Read()
would return False
anyway if no rows were available.
You can have Dispose
called automatically by VB with the Using
statement:
Using cmd As New OleDbCommand(sql, oledbCnn)
'TODO: Work with cmd here.
End Using
Dispose
will be called at the end of the Using
block, even if an error occurs within the Using
block or the Using
block is left by Return
or another statement.
Upvotes: 5
Reputation: 34846
You do not need to check if the data reader has rows every iteration, just check it before you loop.
You are not adding the items to the list, but rather setting the Text
property of cmbDept
, instead do this:
Private Sub cmbCustomer_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmbCustomer.SelectedIndexChanged
sql = "SELECT * from Departments WHERE Customer = '" & cmbCustomer.Text & "'"
Dim cmd As New OleDb.OleDbCommand
cmd.CommandText = sql
cmd.Connection = oledbCnn
dr = cmd.ExecuteReader
If (dr.HasRows) Then
While dr.Read()
cmbDept.Text = CStr((dr("Name"))) <--- 2nd combobox
End While
End If
cmd.Dispose()
dr.Close()
End Sub
Also, it is highly recommended that you use a parameterized query as to avoid a visit from Little Bobby Tables, like this:
Private Sub cmbCustomer_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmbCustomer.SelectedIndexChanged
sql = "SELECT * from Departments WHERE Customer = @Customer"
Dim cmd As New OleDb.OleDbCommand
cmd.Parameters.AddWithValue("@Customer", cmbCustomer.Text)
cmd.CommandText = sql
cmd.Connection = oledbCnn
dr = cmd.ExecuteReader
If (dr.HasRows) Then
While dr.Read()
cmbDept.Text = CStr((dr("Name"))) <--- 2nd combobox
End While
End If
cmd.Dispose()
dr.Close()
End Sub
Upvotes: 4