I have a .csv file that I load in a combo box inside a data grid view. My csv is like this:
prodname,prodcode,amt
prodname1,prodcode1,amt1
prodname2,prodcode2,amt2
prodname
is what I am displaying in the combobox inside the datagridview.
What i want is when I select prodname1
, prodcode1
and amt1
will be displayed on the same row in the data grid view. I am just starting to fumble around in vb.net and will be grateful if someone help me.
This is what I have for now:
Dim cmb As New DataGridViewComboBoxColumn()
cmb.HeaderText = "Product Name"
cmb.Name = "cmb"
DataGridView2.Columns.Add(cmb) 'code for a combobox column in datagridview
Dim filename As String
Dim dt As New DataTable
filename = "/file/path/here"
Dim sr As New IO.StreamReader(filename)
Dim newline() As String = sr.ReadLine.Split(","c)
dt.Columns.AddRange({New DataColumn(newline(0)), _
New DataColumn(newline(1))})
While (Not sr.EndOfStream)
newline = sr.ReadLine.Split(",")
Dim newrow As DataRow = dt.NewRow
cmb.Items.Add(newline(0))
newrow.ItemArray = {newline(1)}
dt.Rows.Add(newrow)
End While
DataGridView2.DataSource = dt
UPDATE:
I updated my code as per Alex's answer but I still get an error.
Dim cmb As New DataGridViewComboBoxColumn()
cmb.HeaderText = "Product Name"
cmb.Name = "cmb"
DataGridView1.Columns.Add(cmb)
AddHandler DataGridView1.CellValueChanged, AddressOf DataGridView1_OnCellValueChanged
AddHandler DataGridView1.CurrentCellDirtyStateChanged, AddressOf DataGridView1_OnCurrentCellDirtyStateChanged
Dim filename As String
filename = "/path/to/file"
Dim sr As New IO.StreamReader(filename)
Dim newline() As String = sr.ReadLine.Split(","c)
dt.Columns.AddRange({New DataColumn(newline(0)), _
New DataColumn(newline(1))})
While (Not sr.EndOfStream)
newline = sr.ReadLine.Split(","c)
Dim newrow As DataRow = dt.NewRow
cmb.Items.Add(newline(0))
'newrow.ItemArray = {newline(1)}
dt.Rows.Add(newrow)
dicItems.Add(newline(0), newline.Skip(1))
End While
DataGridView1.DataSource = dt
End Sub
Private Sub DataGridView1_OnCellValueChanged(ByVal s As Object, ByVal e As DataGridViewCellEventArgs)
If e.ColumnIndex = 0 Then
Dim changedCell = DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex)
For i As Integer = 0 To dt.Columns.Count
dt.Rows(e.RowIndex).Item(i) = dicItems(changedCell.Value.ToString)(i) **error here**
Next
End If
End Sub
Private Sub DataGridView1_OnCurrentCellDirtyStateChanged(ByVal s As Object, ByVal e As EventArgs)
If DataGridView1.IsCurrentCellDirty Then
DataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit)
End If
End Sub
The error says Cannot find column 2
or when I tweak something, the error becomes The given key was not present in the dictionary
on the same line
You need two new Event Handlers:
AddHandler DataGridView1.CellValueChanged, AddressOf DataGridView1_OnCellValueChanged
AddHandler DataGridView1.CurrentCellDirtyStateChanged, AddressOf DataGridView1_OnCurrentCellDirtyStateChanged
The first is to recognize if the cell value of your combobox has changed. The latter is to fire the OnCellValueChanged
when you click on a combobox item (default behavior is that the event is only fired after you leave the cell). Put that code in the Forms constructor or Load
event handler.
Additionally you have to store which prodname
has which details (eg prodname1
=> prodcode1,amt1
). In my example I did this with a Dictionary<Key: string => Values: IEnumerable<string>
.
Class Form1
Private dicItems As New Dictionary(Of String, IEnumerable(Of String))
Private dt As New DataTable
...
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
While (Not sr.EndOfStream)
newline = sr.ReadLine.Split(","c)
Dim newrow As DataRow = dt.NewRow
cmb.Items.Add(newline(0))
dt.Rows.Add(newrow)
'Fill Dicitonary here. Key: newLine(0), values: newLine(1,2,...n)
dicItems.Add(newline(0), newline.Skip(1))
End While
End Sub
The code of the event handlers are pretty straight forward:
Private sub DataGridView1_OnCurrentCellDirtyStateChanged(s As Object, e As EventArgs)
If DataGridView1.IsCurrentCellDirty Then
DataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit)
End If
End sub
=> Fire the CellValueChangedEvent
via Commiting the current combobox item change.
Private sub DataGridView1_OnCellValueChanged(s As Object, e As DataGridViewCellEventArgs)
If e.ColumnIndex = 0 Then
Dim changedCell = DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex)
For i As Integer = 0 To dt.Columns.Count
dt.Rows(e.RowIndex).Item(i) = dicItems(changedCell.Value.ToString)(i)
Next
End If
End sub
=> Check if the combobox has changed ( ColumnIndex = 0
) and get the changed cell.
Lookup in the dictionary to find the corresponding prodcode,amt
with the given key ( prodname
).
Set the new value in the DataTable
(you have to make dt
a class field instead of a variable in your Load method).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.