Search code examples
.netvb.netdatagridviewdatagridviewcombobox

DataGridView bound to list(of T) change column type


I have a datagridview the is bound to a List(of T).

Private BodyComponents As New List(Of BodyComponent)
Private BodyBinding As BindingSource


Public Sub New()

    ' This call is required by the designer.
    InitializeComponent()


    ' Set the bindingsource
    BodyBinding = New BindingSource(BodyComponents, Nothing)

    ' Add any initialization after the InitializeComponent() call.
    dgvBodyOverview.DataSource = BodyBinding

    ....

All the items in the list represent a object with multiple properties, one of these is material As String. I have a large list of available materials where the user should be able to choose from. How can I make this available in the datagridview as drop-down box?

Info: The materials are read at run-time when the dialog is opened and not hardcoded.


Solution

  • You can't change the column types, so after the columns are created replace the Material one with a new DataGridViewComboBoxColumn you created:

    dgv1.DataSource = ...
    
    Dim cbo = New DataGridViewComboBoxColumn()
    Dim oldCol = dgv1.Columns("Material")
    ' copy or set prop values
    cbo.HeaderText = oldCol.HeaderText
    cbo.Name = oldCol.Name
    cbo.DataSource = MaterialsList
    cbo.DataPropertyName = "Material"
    
    ' replace the column
    dgv1.Columns.Remove(oldCol)
    dgv1.Columns.Add(cbo)
    ' cant set the Display Index until it is in the DGV
    cbo.DisplayIndex = oldCol.DisplayIndex
    

    In cases where you need the column to display one thing but save something like an Id to the DGV's DataSource, you'd do that thru the combo column's DataSource.

    Use either a DataTable query result which contains the Id and text you want to show, or a simple List those Name-Value pairs:

    cbo.DataSource = Materials              ' == a DT or List of Name-Id
    cbo.DisplayName = "MaterialName"        ' col or prop name to show
    cbo.ValueMember = "Id"                  ' value to save 
    

    The datatype of the ValueMember needs to match that of the column it maps to in the data source (cbo.DataPropertyName)