TAGS :Viewed: 5 - Published at: a few seconds ago

[ DataGridView combobox column with datasource ]

Have datagridview which contains 4 columns created manually from creator. 1st, 2nd and 3rd columns are just textbox columns but the last one is marked as comboboxcolumn.

User can add rows to it clicks on some button. Values for first three columns are comming from some textboxes. The problem is i have to populate combobx column when user add his row. What i tried so far was like this:

dgvMaterials.Rows.Add(material, rodzajName, rodzajID, new Variation().GetAll())

Note that GetAll function retreiving datatable data inside are Id and Name. Id should be marked as value member and name as display member.

So simply saying user click some button on form tree first column's fields filling up from some textboxes, and last combobox column should be filled up by data from GetAll. How to achieve that?


   Private Sub btnAddMatType_Click(sender As Object, e As EventArgs) Handles btnAddMatType.Click

            try
              Dim dt as DataTable
              dt = New Variation().GetAll()


              Dim cbo = CType(dgvMaterials.Columns(3), DataGridViewComboBoxColumn)
              cbo.Items.AddRange(dt.AsEnumerable().Select(Function(s) s.Field(Of String)("Name")).ToArray())

              Dim rodzajID as String = TreeMaterials.SelectedValue
              Dim rodzajName as string = TreeMaterials.SelectedNode.Text
              Dim material as string = TreeMaterials.SelectedNode.Parent.Text

              dgvMaterials.Rows.Add(material, rodzajName, rodzajID)


Catch ex As Exception
                msgbox(ex.ToString())
End Try

dt contains data: enter image description here

grid look after all (no data in combo): enter image description here

Drilling into cbo.Items: enter image description here

Answer 1


If you created the columns yourself, you just need to add the cbo data.

Dim sql = "SELECT Id, Name FROM Foo"
Dim dt = ... get the dt from db

' cast column 3/Foo to CBO column to access CBO related props
Dim cbo = CType(dgv2.Columns("FooCol"), DataGridViewComboBoxColumn)
cbo.DataSource = dt
cbo.ValueMember = "Id"
cbo.DisplayMember = "Name"

However, this will not work well without a DataSource like a List or DataTable for the DGV - there is no place to store the Id. It would be simple to whip up a small class and a List for this, but it may also be overkill.

Instead, since you manually populate the DGV, just populate the Items collection as well.This code sets up the list for the entire column, so it should be run once only:

Dim cbo = CType(dgv2.Columns("FooCol"), DataGridViewComboBoxColumn)
' get all the names to be used
cbo.Items.AddRange(dt.AsEnumerable().
                   Select(Function(s) s.Field(Of String)("Name")).
                   ToArray())

Adding rows simply involves adding a new row. For the cbo column, you would pass a string indicating the current selection, or skip it maybe for a new row:

' add one or more rows - no Foo data yet
dgv2.Rows.Add("Ziggy", "Orange", 1, "Cat")
dgv2.Rows.Add("Zoey", "Blue", 3)
dgv2.Rows.Add("Zalgo", "Green", 78)

Note that populating the Items collection is a one-time thing. You can add/remove rows as the user select things, but the cbo only needs to be set up once.

If there is data for foo - one of the values from the DataTable - supply it. Unbound, you may need to hold onto the DataTable so you can look up the value/ID for the text selected. Result:

enter image description hereenter image description here


Another alternative would be to copy the TreeView data to a class object and use a PropertyGrid if you are just editing one item at a time. This would allow a TypeConverter to display one thing and save another as a data bound control would.