ComboBox en un DataGrid
Como crear una ComboBox desenlazada en un datagrid

Fecha: 25/Oct/2004 (24/10/2004)
Autor: Alvaro Regalado. alvaritus@msn.com

 


Con este truco trataré de explicar como hice para insertar una combobox en un datagrid. La verdad sea dicha, esto de los datagrids en .Net me ha dado más de un dolor de cabeza. Después si les interesa mando otro con Combos enlazadas y otras cosillas que he aprendido con esta cosa mañosa llamada Datagrid (aunque le he tomado un poco de cariño últimamente)

1) Bueno, lo primero que tenemos que hacer es Crear una clase que herede de DataGridTextBoxColumn, a la que llamaré DataGridComboBoxColumn. Ahí les va el código:

Option Strict Off
Option Explicit On 

Imports System
Imports System.Drawing
Imports System.Windows.Forms

Public Class DataGridComboBoxColumn
    Inherits DataGridTextBoxColumn
    Public WithEvents ColumnComboBox As ComboSinKeyUp
    Private WithEvents _Origen As CurrencyManager
    Private _RenglonNumero As Integer
    Private _EsEdicion As Boolean

    Shared Sub New()
    End Sub

    Public Sub New()
        MyBase.New()
        _Origen = Nothing
        _EsEdicion = False
        ColumnComboBox = New ComboSinKeyUp
        AddHandler ColumnComboBox.Leave, New EventHandler(AddressOf DejarComboBox)
        AddHandler ColumnComboBox.SelectionChangeCommitted, New EventHandler(AddressOf ComboComienzaEdicion)
    End Sub

    Protected Overloads Overrides Sub Edit(ByVal source As CurrencyManager, ByVal rowNum As Integer, ByVal bounds As Rectangle, ByVal     readOnly1 As Boolean, ByVal instantText As String, ByVal cellIsVisible As Boolean)
        MyBase.Edit(source, rowNum, bounds, readOnly1, instantText, cellIsVisible)
        _RenglonNumero = rowNum
        _Origen = source
        ColumnComboBox.Parent = Me.TextBox.Parent
        ColumnComboBox.Location = Me.TextBox.Location
        ColumnComboBox.Size = New Size(Me.TextBox.Size.Width, ColumnComboBox.Size.Height)
        ColumnComboBox.Text = Me.TextBox.Text
        Me.TextBox.Visible = False
        ColumnComboBox.Visible = True
        ColumnComboBox.BringToFront()
        ColumnComboBox.Focus()
    End Sub

    Protected Overloads Overrides Function Commit(ByVal dataSource As CurrencyManager, ByVal rowNum As Integer) As Boolean
        If _EsEdicion Then
            _EsEdicion = False
            SetColumnValueAtRow(dataSource, rowNum, ColumnComboBox.Text)
        End If
        Return True
    End Function

    Private Sub ComboComienzaEdicion(ByVal sender As Object, ByVal e As EventArgs)
        _EsEdicion = True
        MyBase.ColumnStartedEditing(sender)
    End Sub

    Private Sub DejarComboBox(ByVal sender As Object, ByVal e As EventArgs)
        If _EsEdicion Then
            SetColumnValueAtRow(_Origen, _RenglonNumero, ColumnComboBox.Text)
            _EsEdicion = False
            Invalidate()
        End If
        ColumnComboBox.Hide()
    End Sub
End Class

2) Aquí va otra Clase llamada ComboSinKeyUp que hereda del control ComboBox. Lo que hace es ignorar el KeyUp en dicho control...

Public Class ComboSinKeyUp
    Inherits ComboBox
    Private WM_KEYUP As Integer = &H101

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        If m.Msg = WM_KEYUP Then
        'Ignora el keyup para evita problemas de tabulación
            Return
        End If
        MyBase.WndProc(m)
    End Sub
End Class

3) Finalmente en la Form en la que tengo el Datagrid debo aplicarle un TableStyle determinado y dentro del mismo va a estar el tipo que hemos creado en la clase detalla anteriormente. A continuación va el código del TableStyle para una tabla de tres campos en donde la tercera columna es del tipo DataGridComboBoxColumn.

Private Sub AgregarEstiloTabla()
    Dim ts1 As DataGridTableStyle
    ts1 = New DataGridTableStyle
    ts1.MappingName = "Clientes"
    ts1.AlternatingBackColor = Color.LightGray

    Dim TextCol As DataGridTextBoxColumn
    TextCol = New DataGridTextBoxColumn
    TextCol.MappingName = "CliCod"
    TextCol.HeaderText = "Código"
    TextCol.Width = 80
    ts1.GridColumnStyles.Add(TextCol)

    TextCol = New DataGridTextBoxColumn
    TextCol.MappingName = "CliNombre"
    TextCol.HeaderText = "Nombre"
    TextCol.Width = 100
    ts1.GridColumnStyles.Add(TextCol)

    'Aquí viene la referencia a la Combo
    Dim ComboTextCol As New DataGridComboBoxColumn
    'Cambia el estilo de la combo ...
    ComboTextCol.MappingName = "CliPais"
    ComboTextCol.HeaderText = "País"
    ComboTextCol.Width = 100
    ts1.GridColumnStyles.Add(ComboTextCol)
    ComboTextCol.ColumnComboBox.Items.Clear()
    ComboTextCol.ColumnComboBox.Items.Add("España")
    ComboTextCol.ColumnComboBox.Items.Add("Uruguay")
    ComboTextCol.ColumnComboBox.Items.Add("Argentina")
    ComboTextCol.ColumnComboBox.Items.Add("Brasil")
    ComboTextCol.ColumnComboBox.DropDownStyle = ComboBoxStyle.DropDownList
    ts1.PreferredRowHeight = (ComboTextCol.ColumnComboBox.Height + 3)
    dataGrid1.TableStyles.Add(ts1)
End Sub

Final...

Este es el fin por ahora. Les adjunto un ejemplo de lo expuesto en éste truco. Saludos para todos y hasta la próxima.


ir al índice

Fichero con el código de ejemplo: alvarore_ComboEnDatagrid.zip 36 KB