how to make a datagridview cellvaluechange 2 column which trigged loop - vb.net

I am developing a sales order application. I am using a datagridview to fill the sales order.
the field in my datagridview are as per below
ItemCode - ItemDescription - qty - price
The description field is a combobox.
What I want is that when a user input an ItemCode, it automatically check my database and give me the Itemdescription
I also want user to be able to select an item from the ItemDescription which is a combobox, and it wil automatically update my Itemcode.
Private Sub salesorder_dgv_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles salesorder_dgv.CellValueChanged
If salesorder_dgv.Rows.Count > 0 Then
If e.ColumnIndex = 0 Then
Dim READER As SqlDataReader
conn.Open()
Dim query As String
query = "select * from item where code = '" & salesorder_dgv.Rows(e.RowIndex).Cells(0).Value & "'"
cmd = New SqlCommand(query, conn)
READER = cmd.ExecuteReader
If READER.Read Then
salesorder_dgv.Rows(e.RowIndex).Cells(1).Value = READER.GetString(2)
End If
conn.Close()
End If
If e.ColumnIndex = 1 Then
Dim READER As SqlDataReader
conn.Open()
Dim query As String
query = "select * from item where description = '" & salesorder_dgv.Rows(e.RowIndex).Cells(1).Value & "'"
cmd = New SqlCommand(query, conn)
READER2 = cmd.ExecuteReader
If READER.Read Then
salesorder_dgv.Rows(e.RowIndex).Cells(0).Value = READER.GetString(1)
End If
conn.Close()
End If
End If
End Sub
Is there a way to make this code work? i am getting "The Connection was not closed"

There's a lot wrong there so I'll first address what you have to clean it up, then address how you should be doing it.
As suggested in the comments, you should be creating all your ADO.NET objects where you need them, including the connection. You create, use and destroy in the narrowest scope possible. Also, if you only want data from a single column, don't use SELECT *. Retrieve only the column(s) you need. As you're only retrieving data from one column of one row, you should be using ExecuteScalar rather than ExecuteReader.
Next, you should acquaint yourself with the DRY principle, i.e. Don't Repeat Yourself. You have two blocks of code there that are almost identical so you should extract out the common parts and write that only once and pass in the different parts.
Finally, don't use string concatenation to insert values into SQL code. ALWAYS use parameters. It avoids a number of issues, most importantly SQL injection, which is quite possible in your case, as the user is entering free text. With all that in mind, the code you have would be refactored like so:
Private Sub salesorder_dgv_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles salesorder_dgv.CellValueChanged
If salesorder_dgv.RowCount > 0 Then
Dim sourceColumnIndex = e.ColumnIndex
Dim targetColumnIndex As Integer
Dim query As String
Select Case sourceColumnIndex
Case 0
targetColumnIndex = 1
query = "SELECT description FROM item WHERE code = #param"
Case 1
targetColumnIndex = 0
query = "SELECT code FROM item WHERE description = #param"
Case Else
Return
End Select
Dim row = salesorder_dgv.Rows(e.RowIndex)
Dim sourceValue = row.Cells(sourceColumnIndex).Value
Using connection As New SqlConnection("connection string here"),
command As New SqlCommand(query, connection)
command.Parameters.AddWithValue("#param", sourceValue)
connection.Open()
row.Cells(targetColumnIndex).Value = command.ExecuteScalar()
End Using
End If
End Sub
Now to how you should have done it. If you're populating a combo box column with all the descriptions then you must be querying the database for them in the first place. What you should have done is retrieved both the descriptions and the codes in that initial query. That way, you never have to go back to the database. You can populate a DataTable with both the codes and the descriptions and then much of the work will be done for you.
For the example below, I started by setting up the form in the designer, which meant adding and configuring the appropriate columns in the grid and adding the BindingSource components. That also includes setting the DataPropertyName property of each grid column so it binds to the appropriate source column. I'm also manually populating the item data here but you would be getting that data from your database.
Private itemTable As New DataTable
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
LoadItemData()
LoadSaleData()
End Sub
Private Sub LoadItemData()
With itemTable.Columns
.Add("code", GetType(String))
.Add("description", GetType(String))
End With
With itemTable.Rows
.Add("123", "First Item")
.Add("abc", "Second Item")
.Add("789", "Third Item")
.Add("xyz", "Fourth Item")
.Add("01a", "Fifth Item")
End With
itemBindingSource.DataSource = itemTable
With itemDescriptionColumn
.DisplayMember = "Description"
.ValueMember = "Description"
.DataSource = itemBindingSource
End With
End Sub
Private Sub LoadSaleData()
Dim saleTable As New DataTable
With saleTable.Columns
.Add("ItemCode", GetType(String))
.Add("ItemDescription", GetType(String))
.Add("Quantity", GetType(Integer))
.Add("Price", GetType(Decimal))
End With
saleBindingSource.DataSource = saleTable
salesorder_dgv.DataSource = saleBindingSource
End Sub
Private Sub salesorder_dgv_CellValidating(sender As Object, e As DataGridViewCellValidatingEventArgs) Handles salesorder_dgv.CellValidating
If e.RowIndex >= 0 AndAlso
e.ColumnIndex = 0 AndAlso
Not String.IsNullOrEmpty(e.FormattedValue) Then
'Check that the code entered by the user exists.
e.Cancel = (itemBindingSource.Find("code", e.FormattedValue) = -1)
If e.Cancel Then
MessageBox.Show("No such item")
End If
End If
End Sub
Private Sub salesorder_dgv_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles salesorder_dgv.CellValueChanged
Dim rowIndex = e.RowIndex
Dim sourceColumnIndex = e.ColumnIndex
If rowIndex >= 0 And sourceColumnIndex >= 0 Then
Dim sourceColumnName As String
Dim targetColumnName As String
Dim targetColumnIndex As Integer
Select Case sourceColumnIndex
Case 0
sourceColumnName = "code"
targetColumnName = "description"
targetColumnIndex = 1
Case 1
sourceColumnName = "description"
targetColumnName = "code"
targetColumnIndex = 0
Case Else
Return
End Select
Dim itemRow = itemBindingSource(itemBindingSource.Find(sourceColumnName, salesorder_dgv(sourceColumnIndex, rowIndex).Value))
Dim code = CStr(itemRow(targetColumnName))
salesorder_dgv(targetColumnIndex, rowIndex).Value = code
End If
End Sub
You start by populating the items and binding that data to the combo box column and then create an empty DataTable for the sales and bind that to the grid. The code checks that any manually entered codes actually do match items and it will set the description when a code is entered manually and the code when a description is selected from the list. It does this by referring back to the BindingSource containing the item data each time, so no extra queries. You might want to consider retrieving the price data for each item too, and calculating the price for that row based on that and the quantity.

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

Get special max record

I have in my Table1 3 fields (IdFactory Type Numeric-IdSector Type Numeric-NameFactory Type Text).When i click on Button1 i get max record of (IdFactory) in TextBox1.My ComboBox1 is filled with several numbers from 1 to 100.I choose (IdSector) by ComboBox1 and the records in this field (IdSector) repeat only 5 times.How to automatically display max record of (IdSector) in combobox1 when i Click on Button1.this is my code to get max record on TextBox1
ExecuteScalar returns Nothing, not DBNull.Value if no result has been found.
Dim result As Object = Cmd.ExecuteScalar
Dim id As Integer
If result Is Nothing Then
id = 1
Else
id = CInt(result) + 1
End If
TextBox1.Text = id.ToString()
ComboBox1.SelectedItem = id
This assumes that you have added the numbers to the ComboBox as Integer and not as String. If you have added them as String do ComboBox1.SelectedItem = id.ToString().
Keep your data objects local so you can be sure they closed and disposed. The Using...End Using blocks do this for you even if there is an error.
What I think you are after is the IdSector for the highest IdFactory. Although you can't use an aggregate function in a where clause; you can use a sub-query with an aggregate.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim result As Object
Using Conne As New OleDbConnection("Your connection string")
Using Cmd As New OleDbCommand("Select IdSector from Table1 Where IdFactory = (Select max(IdFactory) From Table1);", Conne)
Conne.Open()
result = Cmd.ExecuteScalar
End Using
End Using
If result Is Nothing Then
TextBox1.Text = "1"
ComboBox1.Text = "1"
Else
TextBox1.Text = (CInt(result) + 1).ToString
ComboBox1.Text = result.ToString
End If
End Sub

letting user type and add value to an already bound combobox

I have one combobox in my app that gets populated with a dozen or so items from SQL SERVER. I am currently trying to allow user to be able to type in a new value into the combobox and save it to a table in SQL SERVER. I'm looking for something along the lines of a DropDownStyle of DropDown and DropDownList. Basically I'm hoping to let the user type in the combobox, however if the value is not there, i want to be able to give them an option of saving it (probably on lost focus). I'm wondering what would be a good way of doing something like that.
On lost focus should I basically go through each item that is currently in the drop down and check it against the value entered?
EDIT:
Sql="SELECT IDvalue, TextName from TblReference"
Dim objconn As New SqlConnection
objconn = New SqlConnection(conn)
objconn.Open()
Dim da As New SqlDataAdapter(sql, objconn)
Dim ds As New DataSet
da.Fill(ds, "Name")
If ds.Tables("Name").Rows.Count > 0 Then
Dim dr As DataRow = ds.Tables("Name ").NewRow
ds.Tables("Name").Rows.InsertAt(dr, 0)
With c
.DataSource = ds.Tables("Name")
.ValueMember = " IDvalue "
.DisplayMember = " TextName "
End With
End If
You are already adding a fake/blank row to a table, you can do the same thing for a new item.
' form level datatable var
Private cboeDT As DataTable
Initializing:
cboeDT = New DataTable
Dim sql = "SELECT Id, Descr FROM TABLENAME ORDER BY Descr"
Using dbcon As New MySqlConnection(MySQLConnStr)
Using cmd As New MySqlCommand(sql, dbcon)
dbcon.Open()
cboeDT.Load(cmd.ExecuteReader())
' probably always need this even
' when there are no table rows (???)
Dim dr = cboeDT.NewRow
dr("Id") = -1 ' need a way to identify it
dr("Descr") = ""
cboeDT.Rows.InsertAt(dr, 0)
End Using
End Using
cboeDT.DefaultView.Sort = "Descr ASC"
cboE.DataSource = cboeDT
cboE.DisplayMember = "Descr"
cboE.ValueMember = "Id"
Note Users tend to have a preference as to the order of these things. The simple creatures tend to prefer alphabetical over a DB Id they may never see. To accommodate them, the DefaultView is sorted so that any new rows added will display in the correct order.
Add new items in the Leave event (much like Steve's):
Private Sub cboE_Leave(sender ...
' if it is new, there will be no value
If cboE.SelectedValue Is Nothing Then
' alternatively, search for the text:
'Dim item = cboeDT.AsEnumerable().
' FirstOrDefault(Function(q) String.Compare(q.Field(Of String)("Descr"),
' cboE.Text, True) = 0)
'If item Is Nothing Then
' ' its new...
Dim newid = AddNewItem(cboE.Text)
Dim dr = cboeDT.NewRow
dr("Id") = newid
dr("Descr") = cboE.Text
cboeDT.Rows.Add(dr)
' fiddling with the DS looses the selection,
' put it back
cboE.SelectedValue = newid
End If
End Sub
If you want to search by text:
Dim item = cboeDT.AsEnumerable().
FirstOrDefault(Function(q) String.Compare(q.Field(Of String)("Descr"),
cboE.Text, True) = 0)
If item Is Nothing Then
' its new...
...
Inserting will vary a little depending on the actual db. A key step though is to capture and return the ID of the new item since it is needed for the CBO:
Private Function AddNewItem(newItem As String) As Int32
Dim sql = "INSERT INTO MY_TABLE (Descr) VALUES (#v); SELECT LAST_INSERT_ID();"
Dim newId = -1
Using dbcon As New MySqlConnection(MySQLConnStr)
Using cmd As New MySqlCommand(sql, dbcon)
dbcon.Open()
cmd.Parameters.Add("#v", MySqlDbType.String).Value = newItem
' MySql provides it in the command object
If cmd.ExecuteNonQuery() = 1 Then
newId = Convert.ToInt32(cmd.LastInsertedId)
End If
End Using
End Using
Return newId
End Function
As noted MySql provides the LastInsertedID as a command object property. In SQL SERVER, tack ...";SELECT LAST_INSERT_ID();" to the end of your SQL and then:
newId = Convert.ToInt32(cmd.ExecuteScalar())
This is not conceptually very different from Steve's answer, except it uses the DataTable you build rather than collections which makes it (very) slightly simpler.
The way I do this, is on window load I perform a new SQL query to get the list of values in the table, and load them into a combobox.
Then once focus is lost, it then checks what's currently typed into the combobox against the current values already loaded. If it doesn't exist, then it's not in SQL. Something like the following...
Dim found As Boolean = False
For i As Integer = 0 To comboBox.Items.Count - 1
Dim value As String = comboBox.Items(i).ToString()
If comboBox.Text = value Then
found = True
End If
Next
If found = False Then
'the item doesn't exist.. add it to SQL
Else
'the item exists.. no need to touch SQL
End If
First thing I would do is to build a simple class to hold your values through a List of this class
Public Class DataItem
Public Property IDValue As Integer
Public Property TextName as String
End Class
Now, instead of building an SqlDataAdapter and fill a dataset, work with an SqlDataReader and build a List(Of DataItem)
' Class global...
Dim allItems = new List(Of DataItem)()
Sql="SELECT IDvalue, TextName from TblReference"
' Using to avoid leaks on disposable objects
Using objconn As New SqlConnection(conn)
Using cmd As New SqlCommand(Sql, objconn)
objconn.Open()
Using reader = cmd.ExecuteReader()
While reader.Read()
Dim item = new DataItem() With { .IDValue = reader.GetInt32(0), .TextName = reader.GetString(1)}
allItems.Add(item)
End While
End Using
if allItems.Count > 0 Then
allItems.Insert(0, new DataItem() With {.IDValue = -1, .TextValue = ""}
Dim bs = new BindingList(Of DataItem)(allItems)
c.DataSource = bs
c.ValueMember = "IDvalue"
c.DisplayMember = "TextName"
End If
End Using
End Using
Now the code that you want to add to your Leave event for the combobox
Sub c_Leave(sender As Object, e As EventArgs) Handles c.Leave
If Not String.IsNullOrEmpty(c.Text) Then
Dim bs = DirectCast(c.DataSource, BindingList(Of DataItem))
if bs.FirstOrDefault(Function(x) x.TextName = c.Text) Is Nothing Then
Dim item = new DataItem() With { .IDValue = -1, .TextName = c.Text}
bs.Add(item)
' here add the code to insert in the database
End If
End If
End Sub

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

How to fill a ComboBox on the selection change from second ComboBox

I have two comboBoxes, one is CountryCombo and second is StateCombo.
What I want is the that when i the clicks country combo and select a one country then the States of that the country should get populated in the State Combo.
I have tried things many many many but nothing working. Below is my code of how my CountryCombo is getting filled.
query="select CountryName from CountryMaster"
if dr.hasRows()
{
while dr.read()
{
countrycombo.items.add(dr(0)
}
}
Please check the below code,and please do some homework before posting a question.
Private Sub countryCombo_SelectedValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedValueChanged
Dim query As String
query = "select StateName from StateMaster where CountryId='" & countryCombo.SelectedValue & "'"
if dr.hasRows()
{
while dr.read()
{
Statecombo.items.add(dr(0))
}
}
End Sub
This will populate your Statecombo on the selection change of countryCombo.
Try this code:
Dim dt As New DataTable
Dim cm1, cm2 As New DataColumn
cm1.ColumnName = "CountryName"
cm1.DataType = GetType(String)
cm2.ColumnName = "CountryID"
cm2.DataType = GetType(String) 'or integer
dt.Columns.Add(cm1)
dt.Columns.Add(cm2)
'contry = here select your data
Dim dr As DataRow
dr = dt.NewRow
dr(0) = "Select One"
dr(1) = "-1"
dt.Rows.Add(dr)
For Each item In contry
dr = dt.NewRow
dr(0) = item.CountryName
dr(1) = item.CountryID
dt.Rows.Add(dr)
Next
Drp.DataSource = dt
Drp.DataTextField = "CountryName"
Drp.DataValueField = "CountryID"
Drp.DataBind()
with this code you can fill your dropdown. you can write sub like this and put it on selected change of this dropdown. Have good time!
add this part and make sure you have post back on dropdown list if its web form.
Protected Sub Drpcountry_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Drpcountry.SelectedIndexChanged
Dim db as new linqdatacontext
Dim dt As New DataTable
Dim cm1, cm2 As New DataColumn
cm1.ColumnName = "stateName"
cm1.DataType = GetType(String)
cm2.ColumnName = "stateID"
cm2.DataType = GetType(String) 'or integer
dt.Columns.Add(cm1)
dt.Columns.Add(cm2)
Dim stateslist = From i in db.tb_states where i.countryid = drpcountry.selectedvalue select i
Dim dr As DataRow
dr = dt.NewRow
dr(0) = "Select One"
dr(1) = "-1"
dt.Rows.Add(dr)
For Each item In stateslist
dr = dt.NewRow
dr(0) = item.stateName
dr(1) = item.stateID
dt.Rows.Add(dr)
Next
Drpstate.DataSource = dt
Drpstate.DataTextField = "stateName"
Drpstate.DataValueField = "stateID"
Drpstate.DataBind()
End Sub
the code you show is the (incomplete) code that fills your CountryCombo : Please share also the code that fills the StateCombo on new Country Selection, since it is that part that causes you problems.
Anyway you should avoid manipulating directly ComBoBox items, and instead you Should Bind both Combo To ObservableCollection, say to
Public Property CountryCollection as New ObservableCollection(Of Country)
and
Public Property StateCollection As New ObservableCollection(Of State).
And for both Country and State Object, overload ToString() sub to have Country/State name displayed
in the Combos.
Now fill the CountryCollection with your countries, and on a SelectionChanged of the CountryCombo, retrieve the list of state ( = state having CountryCombo.SelectedItem.CountryID as CountryID) then populate your StateCollection with this query result (Clear() then add()).
Test step by step : check that your country / state queries are returning good results with BreakPoints/ Debugger. If you bind to ObservableCollection, the queries should now be the only problem.