Llenar un campo DataGridViewComboBoxColumn de un DataGridView desde la base de datos

Problema: Llenar una columna combo en mi grid.
Solución: Paciencia y la explicación a continuación.

Una columna combo se trabaja de forma diferente a una columna texto, primero se tiene que llenar los items que tendrá el combo antes de pasar toda la información al grid.

Existen varias maneras de llenar el campo combo. De forma manual ingresando los items en modo de edición, o con un proceso sencillo en modo de ejecución.

Desgraciadamente, para mi ejemplo, no puedo usar ninguna de las maneras anteriores, puesto que necesito llenar el combo, con los datos de una tabla. Así que tuve que crear mi propio proceso.

Private Sub cargar_DataCombo(ByVal dv As DataGridView)
        Dim adapter As New SqlDataAdapter
               
        Using connection As SqlConnection = New SqlConnection(args) 'La variable args contiene la cadena de conexión, llenada anteriormente.
                adapter = New SqlDataAdapter(select campo_codigo, campo_descripcion from tabla, connection)
               
                'Lleno el DataTable
                Dim dt As New DataTable()
                adapter.Fill(dt)
               
                'Indico la columna combo
                Dim column As DataGridViewComboBoxColumn = _
                DirectCast(dv.Columns(0), DataGridViewComboBoxColumn)
               
                'Configuro la columna.
                With column
                        'Origen de datos
                        .DataSource = dt
                        'Nombre del campo cuyos datos se mostraran en la columna
                        .DisplayMember = "campo_descripcion"
                        'Nombre del campo cuyo valor se devolverá cuando se seleccione un elemento.
                        .ValueMember = "campo_codigo"
                End With
        End Using       
End Sub

El proceso cargar_DataCombo debe ser llamado desde el load de la aplicación, o antes de llenar el grid con la información. Esto quedaría más o menos así:

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        cargar_DataCombo(DataGridView1)
        'Aquí sigue el proceso de llenar los datos al grid
End Sub

Nota: La función DirectCast sirve para cambiar el tipo de dato a otro compatible, parecida a la función CInt que convierte los datos en enteros, la diferencia es que al DirectCast se le debe indicar el tipo al cual se lo debe convertir.

Una vez que tengo mi SP con el select resultante, lo he ejecutado en visual basic .net y lo he llenado en un DataTable, estoy lista para ponerlo en el grid.

DataGridView1.AutoGenerateColumns = False 'Aquí digo que las columnas no se generen automáticamente, sino que yo las lleno manualmente

With DataGridView1
        .Columns(0).DataPropertyName = "NombreCampo1" 'Este es el titulo de la columna del select en el SP
        .Columns(1).DataPropertyName = "NombreCampo2"
End With

Me.DataGridView1.DataSource = dtTabla 'Aquí conecto los datos del DataTable con el grid

¡HORROR! Me da error al cargar el campo combo.

Esto generalmente sucede porque en el DataPropertyName de una columna combo suelo poner la descripción o el texto del combo, cuando en realidad se debe poner el código del mismo, o mejor dicho, el mismo campo que se configura en el ValueMember del combo.

Me explico mejor.

'Cuando configuro la columna combo al llenarla por primera vez
With column
        'Nombre del campo cuyos datos se mostraran en la columna
        .DisplayMember = "campo_descripcion"
        'Nombre del campo cuyo valor se devolverá cuando se seleccione un elemento.
        .ValueMember = "campo_codigo"
End With

'Cuando lleno el campo combo del grid con los datos del select resultante del SP
With DataGridView1
        .Columns(0).DataPropertyName = "campo_codigo" 'Este es el titulo de la columna del select en el SP del combo
End With

Note que campo_codigo es el ValueMember de la columna combo, eso es lo que debe llenarse cuando lleno las columnas del grid.