Link to home
Start Free TrialLog in
Avatar of running32
running32

asked on

Add button to unbound row in datagrid

I can add to a column to my Datagrid titled Survey but how can I add a button to this column?  Thank you for your help

 myDataSet.Tables(0).Columns.Add("Survey", Type.GetType("System.Boolean"), False)

 Dim dr As DataRow
            For Each dr In myDataSet.Tables(0).Rows
           
            Next
Avatar of vadim63
vadim63
Flag of United States of America image

Avatar of running32
running32

ASKER

I tried this, but I want to put a combo box and button in a datagrid.

Thanks
ASKER CERTIFIED SOLUTION
Avatar of jake072
jake072
Flag of Canada image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
ComboBox w/ AutoComplete

Option Strict On
Option Explicit On

Imports System.Collections
Imports System.ComponentModel
Imports System.Drawing
Imports System.Windows.Forms
Imports System.Data

Public Class DataGridComboBox
    Inherits ComboBox
      Public Sub New()
            MyBase.New()
    End Sub

    Public isInEditOrNavigateMode As Boolean = True
    Private setIndex As Int32
    Private processCLOSEUP As Boolean = True

    Private bForceFound As Boolean = False

    Public Event ChangeIndex(ByVal sender As Object, ByVal e As System.EventArgs)

    Const WM_KEYUP As Int32 = &H101
    Const WM_KEYDOWN As Int32 = &H100
    Const CBN_DROPDOWN As Int32 = &H7
    Const CBN_CLOSEUP As Int32 = &H8
    Const CBN_SELENDOK As Int32 = &H9
    Const CBN_SELCHANGE As Int32 = &H1
    Const WM_COMMAND As Int32 = &H111
    Const WM_USER As Int32 = &H400
    Const OCM__BASE As Int32 = WM_USER + &H1C00
    Const OCM_COMMAND As Int32 = OCM__BASE + WM_COMMAND

    Sub New(ByVal bForceFound As Boolean)
        Me.bForceFound = bForceFound
    End Sub

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)

        Select Case m.Msg
            Case OCM_COMMAND
                Dim mIntPtr As Int32 = m.WParam.ToInt32
                'Get notification of combobox list dropdown
                'and enable setting index on list
                'closeup
                If (mIntPtr >> 16) = CBN_DROPDOWN Then
                    processCLOSEUP = True
                End If
                'If user selects an item in the list portion while dropped down
                'disable setting index on closeup
                If (mIntPtr >> 16) = CBN_SELENDOK Then
                    processCLOSEUP = False
                End If
                'If list portion is closing and user
                'has not made a specific selection in
                'the list area, set index
                If processCLOSEUP Then
                    If (mIntPtr >> 16) = CBN_CLOSEUP Then
                        If Me.Items.Count > 0 Then
                            Me.SelectedIndex = setIndex
                        End If
                    End If
                End If
        End Select
        MyBase.WndProc(m)

    End Sub

    Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean

        Select Case msg.WParam.ToInt32()
            Case CInt(Keys.Up)
                If MyBase.Items.Count > 0 And MyBase.SelectedIndex > 0 Then
                    If MyBase.DroppedDown = False Then
                        MyBase.DroppedDown = True
                    End If
                    MyBase.SelectedIndex -= 1
                    setIndex = MyBase.SelectedIndex
                End If
                Return True

            Case CInt(Keys.Down)
                If MyBase.Items.Count > 0 And MyBase.SelectedIndex < MyBase.Items.Count - 1 Then
                    If MyBase.DroppedDown = False Then
                        MyBase.DroppedDown = True
                        processCLOSEUP = True
                    End If
                    MyBase.SelectedIndex += 1
                    setIndex = MyBase.SelectedIndex
                End If
                Return True

            Case CInt(Keys.Right)
                Return True

            Case CInt(Keys.Left)
                Return False

        End Select
        Return MyBase.ProcessCmdKey(msg, keyData)

    End Function 'ProcessCmdKey

    Protected Overrides Function ProcessKeymessage(ByRef m As System.Windows.Forms.Message) As Boolean
        'Handles the tab key skipping over columns
        If m.Msg = WM_KEYUP Then
            If m.WParam.ToInt32 = CInt(Keys.Tab) Then
                Return True
            ElseIf m.WParam.ToInt32 = CInt(Keys.Up) Or m.WParam.ToInt32 = CInt(Keys.Down) Then
                'Combo_KeyDown(New Object, New KeyEventArgs(CType(m.WParam.ToInt32, Keys)))
                Return True
            Else
                Return MyBase.ProcessKeyMessage(m)
            End If
        Else
            Return MyBase.ProcessKeyMessage(m)
        End If
    End Function

    Private Sub Combo_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyUp

        ' Do nothing for certain keys such as navigation keys
        With e
            If ((e.KeyCode = Keys.Back) Or _
             (.KeyCode = Keys.Enter) Or _
             (.KeyCode = Keys.Left) Or _
             (.KeyCode = Keys.Right) Or _
             (.KeyCode = Keys.Up) Or _
             (.KeyCode = Keys.Delete) Or _
             (.KeyCode = Keys.Down) Or _
             (.KeyCode = Keys.PageUp) Or _
             (.KeyCode = Keys.PageDown) Or _
             (.KeyCode = Keys.Home) Or _
             (.KeyCode = Keys.ShiftKey) Or _
             (.KeyCode = Keys.End) Or _
             (.KeyCode = Keys.Tab AndAlso .KeyCode = Keys.Shift)) Then

                Return
            End If
        End With

        ' Store the actual text that has been typed
        Dim TypedText As String = Text

        Dim index As Integer = FindString(TypedText)
        ' Get the text of the first match
        If index > -1 Then

            Dim foundText As String = Me.GetItemText(Items(index))

            Dim sAppendText As String = foundText.Substring(TypedText.Length)
            Text = TypedText & sAppendText

            ' Select the portion of the text that was automatically
            ' added so further typing will replace it
            SelectionStart = TypedText.Length
            SelectionLength = sAppendText.Length
            SelectedIndex = index
            'For setting the the index using
            'CBN_CLOSEUP notification (no user selection
            'in dropped down list portion
            If processCLOSEUP Then
                Me.setIndex = index
            End If

        Else
            'Enforces not in list
            If bForceFound = True Then
                ResetText()
            End If
        End If

    End Sub

    Private Sub Combo_SelectionChangeCommitted(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.SelectionChangeCommitted
        RaiseEvent ChangeIndex(sender, e)
    End Sub

    'Private Sub Combo_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
    '    If Me.Items.Count > 0 Then
    '        Select Case e.KeyCode
    '            Case Keys.Down
    '                If Me.SelectedIndex < Me.Items.Count - 1 Then
    '                    Me.SelectedIndex += 1
    '                Else
    '                    Me.SelectedIndex = 0
    '                End If
    '            Case Keys.Up
    '                If Me.SelectedIndex > 0 Then
    '                    Me.SelectedIndex -= 1
    '                Else
    '                    Me.SelectedIndex = Me.Items.Count - 1
    '                End If
    '        End Select
    '    End If
    'End Sub

End Class


Public Class DataGridComboBoxColumnStyle

    Inherits DataGridColumnStyle
    '
    ' UI constants    
    '
    Private xMargin As Integer = 2
    Private yMargin As Integer = 0
    '
    '
    Public WithEvents Combo As DataGridComboBox
    Private m_DisplayMember, m_ValueMember As String
    Private WithEvents cm As CurrencyManager
    Private dV As New DataView
    Private mDropDown As Boolean
    '
    ' Used to track editing state
    '
    Private OldVal As String = String.Empty
    Private InEdit As Boolean = False

    Private bForceFound As Boolean
    Private bAllowNew As Boolean

    Public Event CreateNew(ByVal strText As String)
    Public Event SelectedValue_Changed(ByVal sender As Object, ByVal e As EventArgs)
    Public Event Leave()

#Region " New "

    Public Sub New()
    End Sub

    ' DATATABLE
    ' Create a new column - DisplayMember, ValueMember
    ' Passed by ordinal
    '
    Public Sub New(ByVal DataSource As DataTable, ByVal DisplayMember As Integer, ByVal ValueMember As Integer, ByVal _DropDownWidth As Integer, Optional ByVal bAllowNew As Boolean = True, Optional ByVal DropDownOnEdit As Boolean = True, Optional ByVal ForceFind As Boolean = False)

        Me.bForceFound = ForceFind
        Me.Combo = New DataGridComboBox(bForceFound)
        Me.bAllowNew = bAllowNew

        InEdit = False

        Me.m_DisplayMember = DataSource.Columns.Item(index:=DisplayMember).ToString
        Me.m_ValueMember = DataSource.Columns.Item(index:=ValueMember).ToString

        With Me.Combo
            .Visible = False
            .DataSource = DataSource
            .DisplayMember = m_DisplayMember
            .ValueMember = m_ValueMember
            .DropDownStyle = ComboBoxStyle.DropDown
            .DropDownWidth = _DropDownWidth
            .MaxDropDownItems = 20
            mDropDown = DropDownOnEdit
            AddHandler .Enter, AddressOf Me.DataGridComboBox_Enter
            AddHandler .Leave, AddressOf DataGridComboBox_Leave
            AddHandler .KeyPress, AddressOf DataGridComboBox_KeyPress
        End With

        Me.dV = DataSource.DefaultView

    End Sub
    ' DATATABLE
    ' Create a new column - DisplayMember, ValueMember
    ' passed by string
    '
    Public Sub New(ByVal DataSource As DataTable, ByVal DisplayMember As String, ByVal ValueMember As String, ByVal _DropDownWidth As Integer, Optional ByVal bAllowNew As Boolean = True, Optional ByVal DropDownOnEdit As Boolean = True, Optional ByVal ForceFind As Boolean = False)

        Me.bForceFound = ForceFind
        Me.Combo = New DataGridComboBox(bForceFound)
        Me.bAllowNew = bAllowNew

        InEdit = False

        With Me.Combo
            .Visible = False
            .DataSource = DataSource
            .DisplayMember = DisplayMember
            .ValueMember = ValueMember
            .DropDownStyle = ComboBoxStyle.DropDown
            .DropDownWidth = _DropDownWidth
            .MaxDropDownItems = 20
            mDropDown = DropDownOnEdit
            AddHandler .Enter, AddressOf Me.DataGridComboBox_Enter
            AddHandler .Leave, AddressOf DataGridComboBox_Leave
            AddHandler .KeyPress, AddressOf DataGridComboBox_KeyPress
        End With

        Me.dV = DataSource.DefaultView

    End Sub
    ' DATVIEW
    ' Create a new column - DisplayMember, ValueMember
    ' Passed by ordinal
    '
    Public Sub New(ByVal DataSource As DataView, ByVal DisplayMember As Integer, ByVal ValueMember As Integer, ByVal _DropDownWidth As Integer, Optional ByVal bAllowNew As Boolean = True, Optional ByVal DropDownOnEdit As Boolean = True, Optional ByVal ForceFind As Boolean = False)

        Me.bForceFound = ForceFind
        Me.Combo = New DataGridComboBox(bForceFound)
        Me.bAllowNew = bAllowNew

        InEdit = False

        Me.m_DisplayMember = DataSource.Table.Columns.Item(index:=DisplayMember).ToString
        Me.m_ValueMember = DataSource.Table.Columns.Item(index:=ValueMember).ToString

        With Me.Combo
            .Visible = False
            .DataSource = DataSource
            .DisplayMember = m_DisplayMember
            .ValueMember = m_ValueMember
            .DropDownStyle = ComboBoxStyle.DropDown
            .DropDownWidth = _DropDownWidth
            .MaxDropDownItems = 20
            mDropDown = DropDownOnEdit
            AddHandler .Enter, AddressOf Me.DataGridComboBox_Enter
            AddHandler .Leave, AddressOf DataGridComboBox_Leave
            AddHandler .KeyPress, AddressOf DataGridComboBox_KeyPress
        End With

        Me.dV = DataSource

    End Sub
    ' DATAVIEW
    ' Create a new column - DisplayMember, ValueMember
    ' passed by string
    '
    Public Sub New(ByVal DataSource As DataView, ByVal DisplayMember As String, ByVal ValueMember As String, ByVal _DropDownWidth As Integer, Optional ByVal bAllowNew As Boolean = True, Optional ByVal DropDownOnEdit As Boolean = True, Optional ByVal ForceFind As Boolean = False)

        Me.bForceFound = ForceFind
        Me.Combo = New DataGridComboBox(bForceFound)
        Me.bAllowNew = bAllowNew

        InEdit = False

        With Me.Combo
            .Visible = False
            .DataSource = DataSource
            .DisplayMember = DisplayMember
            .ValueMember = ValueMember
            .DropDownStyle = ComboBoxStyle.DropDown
            .DropDownWidth = _DropDownWidth
            .MaxDropDownItems = 20
            mDropDown = DropDownOnEdit
            AddHandler .Enter, AddressOf Me.DataGridComboBox_Enter
            AddHandler .Leave, AddressOf DataGridComboBox_Leave
            AddHandler .KeyPress, AddressOf DataGridComboBox_KeyPress
        End With

        Me.dV = DataSource

    End Sub

#End Region

    '
    '------------------------------------------------------
    ' Methods overridden from DataGridColumnStyle
    '------------------------------------------------------
    '
    ' Abort Changes
    '
    Protected Overloads Overrides Sub Abort(ByVal RowNum As Integer)

        RollBack()
        HideComboBox()
        EndEdit()
    End Sub
    '
    ' Commit Changes
    '
    Protected Overloads Overrides Function Commit(ByVal DataSource As CurrencyManager, ByVal RowNum As Integer) As Boolean
        If bForceFound = False And bAllowNew = True Then
            Dim strFoundText As String = Me.Combo.Text
            If Me.Combo.FindStringExact(strFoundText) = -1 And strFoundText.Length > 0 Then
                If MessageBox.Show("Cannot find Item: '" & strFoundText & "'" & vbCrLf & "Would you like to create a new Item ?", "Create New", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.Yes Then
                    RaiseEvent CreateNew(strFoundText)
                    InEdit = True
                End If
            End If
        End If

        HideComboBox()

        If Not InEdit Then
            Return True
        End If

        InEdit = False

        Try

            Dim Value As Object = Me.Combo.SelectedValue
            If NullText.Equals(Value) Then
                Value = Convert.DBNull
            End If
            SetColumnValueAtRow(DataSource, RowNum, Me.Combo.SelectedValue)

        Catch ex As Exception
            Debug.WriteLine(ex.ToString)
            RollBack()
            Return False
        End Try

        EndEdit()

        Return True

    End Function
    '
    ' Try to Handle SelectionChangeCommitted...
    '
    Protected Sub SelectionChanged(ByVal sender As Object, ByVal e As EventArgs) Handles Combo.ChangeIndex
        ' If the parent of the datagrid is a form...
        If TypeOf (MyBase.DataGridTableStyle.DataGrid.Parent) Is Form Then
            ' Get a reference to the form, to get the currencymanager.
            Dim frm As Form = CType(MyBase.DataGridTableStyle.DataGrid.Parent, Form)
            ' Get the currency manager associated with the form.
            Dim cm As CurrencyManager = CType(frm.BindingContext(MyBase.DataGridTableStyle.DataGrid.DataSource, MyBase.DataGridTableStyle.DataGrid.DataMember), CurrencyManager)

            ' Try and set the value.
            Try
                SetColumnValueAtRow(cm, MyBase.DataGridTableStyle.DataGrid.CurrentRowIndex, Me.Combo.SelectedValue)
            Catch ex As Exception
                Debug.WriteLine(ex.Message)
            End Try
        End If
    End Sub
    '
    ' Edit Grid
    '
    Protected Overloads Overrides Sub Edit(ByVal Source As CurrencyManager, ByVal Rownum As Integer, ByVal Bounds As Rectangle, ByVal [ReadOnly] As Boolean, ByVal InstantText As String, ByVal CellIsVisible As Boolean)

        Try

            With Me.Combo

                '.Text = String.Empty

                Dim OriginalBounds As Rectangle = Bounds

                OldVal = .Text

                If CellIsVisible Then
                    Bounds.Offset(xMargin, yMargin)
                    Bounds.Width -= xMargin * 2
                    Bounds.Height -= yMargin
                    .Bounds = Bounds
                    .Visible = True

                Else
                    .Bounds = OriginalBounds
                    .Visible = False
                End If

                If .FindStringExact(.Text) > -1 Then
                    .SelectedValue = GetColumnValueAtRow(Source, Rownum)
                Else
                    .SelectedIndex = -1
                End If

                If Not InstantText Is Nothing Then
                    .SelectedValue = InstantText
                Else
                    .Select(.Text.Length, 0)
                End If

                .RightToLeft = Me.DataGridTableStyle.DataGrid.RightToLeft
                .Focus()

                If .Visible Then
                    Me.DataGridTableStyle.DataGrid.Invalidate(OriginalBounds)
                End If

            End With

            InEdit = True

        Catch ex As Exception
            Debug.WriteLine(ex.ToString)
            InEdit = False
            RollBack()

        End Try

    End Sub

    Protected Overloads Overrides Function GetMinimumHeight() As Integer
        Return Me.Combo.PreferredHeight + yMargin
    End Function

    Protected Overloads Overrides Function GetPreferredHeight(ByVal g As Graphics, _
     ByVal Value As Object) As Integer
        Dim NewLineIndex As Integer = 0
        Dim NewLines As Integer = 0
        Dim ValueString As String = Me.GetTxt(Value)
        Do
            While NewLineIndex <> -1
                NewLineIndex = ValueString.IndexOf("r\n", NewLineIndex + 1)
                NewLines += 1
            End While
        Loop

        Return FontHeight * NewLines + yMargin
    End Function

    Protected Overloads Overrides Function GetPreferredSize(ByVal g As Graphics, _
      ByVal Value As Object) As Size
        Dim Extents As Size = Size.Ceiling(g.MeasureString(GetTxt(Value), _
          Me.DataGridTableStyle.DataGrid.Font))
        Extents.Width += xMargin * 2 + DataGridTableGridLineWidth
        Extents.Height += yMargin
        Return Extents
    End Function

    Protected Overloads Overrides Sub Paint(ByVal g As Graphics, _
     ByVal Bounds As Rectangle, _
     ByVal Source As CurrencyManager, _
     ByVal RowNum As Integer)

        Paint(g, Bounds, Source, RowNum, False)
    End Sub

    Protected Overloads Overrides Sub Paint(ByVal g As Graphics, _
     ByVal Bounds As Rectangle, _
     ByVal Source As CurrencyManager, _
     ByVal RowNum As Integer, _
     ByVal AlignToRight As Boolean)

        Dim Text As String = GetTxt(GetColumnValueAtRow(Source, RowNum))
        PaintText(g, Bounds, Text, RowNum, AlignToRight)
    End Sub

    Protected Overloads Sub Paint(ByVal g As Graphics, _
       ByVal Bounds As Rectangle, _
       ByVal Source As CurrencyManager, _
       ByVal RowNum As Integer, _
       ByVal BackBrush As Brush, _
       ByVal ForeBrush As Brush, _
       ByVal AlignToRight As Boolean)

        Dim Text As String = GetTxt(GetColumnValueAtRow(Source, RowNum))
        PaintText(g, Bounds, Text, BackBrush, ForeBrush, RowNum, AlignToRight)
    End Sub

    Protected Overloads Overrides Sub SetDataGridInColumn(ByVal Value As DataGrid)
        MyBase.SetDataGridInColumn(Value)
        If Not (Me.Combo.Parent Is Value) Then
            If Not (Me.Combo.Parent Is Nothing) Then
                Me.Combo.Parent.Controls.Remove(Me.Combo)
            End If
        End If

        If Not (Value Is Nothing) Then Value.Controls.Add(Me.Combo)
    End Sub

    Protected Overloads Overrides Sub UpdateUI(ByVal Source As CurrencyManager, _
     ByVal RowNum As Integer, ByVal InstantText As String)

        If Not (InstantText Is Nothing) Then
            Me.Combo.Text = InstantText
        End If
    End Sub

    '----------------------------------------------------------------------
    ' Helper Methods
    '----------------------------------------------------------------------

    Private ReadOnly Property DataGridTableGridLineWidth() As Integer
        Get
            If DataGridTableStyle.GridLineStyle = DataGridLineStyle.Solid Then
                Return 1
            Else
                Return 0
            End If
        End Get

    End Property

    Public Sub SetDataSource(ByVal dt As DataTable)
        Me.Combo.DataSource = dt
    End Sub


    Private Sub EndEdit()
        InEdit = False
        Invalidate()
    End Sub

    Private Function GetTxt(ByVal s As Object) As String

        Try

            If s Is DBNull.Value Then Return NullText
            If Not s Is Nothing Then
                'Set up the delimiters for the search string based on TypeOf s
                Dim strFilter As String = String.Empty

                If TypeOf (Me.Combo.ValueMember) Is String Then
                    strFilter = "'" & s.ToString & "'"
                ElseIf TypeOf (Me.Combo.ValueMember) Is DateTime Then
                    strFilter = "#" & s.ToString & "#"
                Else
                    strFilter = s.ToString
                End If

                'Use datatable.select method

                Dim drarr() As DataRow = Me.dV.Table.Select(Me.Combo.ValueMember & " = " & strFilter)

                If drarr.Length > 0 Then      'Value found
                    'Return associated Display Member
                    Return drarr(0)(Me.Combo.DisplayMember).ToString
                Else      'Value NOT found
                    Return String.Empty
                End If
            Else
                Return String.Empty
            End If

        Catch ex As Exception
            Console.WriteLine(ex.ToString)
        End Try

    End Function


    Private Sub HideComboBox()

        If Me.Combo.Focused Then
            Me.DataGridTableStyle.DataGrid.Focus()
        End If
        Me.Combo.Visible = False

    End Sub

    Private Sub RollBack()
        Me.Combo.Text = OldVal
    End Sub

    Private Sub PaintText(ByVal g As Graphics, ByVal Bounds As Rectangle, ByVal Text As String, ByVal RowNum As Integer, _
        ByVal AlignToRight As Boolean)

        Dim BackBrush As Brush
        Dim ForeBrush As Brush = New SolidBrush(DataGridTableStyle.ForeColor)
        If Me.DataGridTableStyle.DataGrid.IsSelected(RowNum) Then
            BackBrush = New SolidBrush(DataGridTableStyle.SelectionBackColor)
        Else
            BackBrush = New SolidBrush(DataGridTableStyle.BackColor)
        End If
        PaintText(g, Bounds, Text, BackBrush, ForeBrush, RowNum, AlignToRight)

    End Sub

    Private Sub PaintText(ByVal g As Graphics, ByVal TextBounds As Rectangle, ByVal Text As String, ByVal BackBrush As Brush, _
        ByVal ForeBrush As Brush, ByVal RowNum As Integer, ByVal AlignToRight As Boolean)

        Dim Rect As Rectangle = TextBounds
        Dim RectF As RectangleF = RectF.op_Implicit(Rect)    ' Convert to RectangleF
        Dim Format As StringFormat = New StringFormat

        If AlignToRight Then
            Format.FormatFlags = StringFormatFlags.DirectionRightToLeft
        End If

        Select Case Me.Alignment
            Case HorizontalAlignment.Left
                Format.Alignment = StringAlignment.Near
            Case HorizontalAlignment.Right
                Format.Alignment = StringAlignment.Far
            Case HorizontalAlignment.Center
                Format.Alignment = StringAlignment.Center
        End Select

        Format.FormatFlags = Format.FormatFlags Or StringFormatFlags.NoWrap
        g.FillRectangle(Brush:=BackBrush, Rect:=Rect)

        Rect.Offset(0, yMargin)
        Rect.Height -= yMargin
        g.DrawString(Text, Me.DataGridTableStyle.DataGrid.Font, ForeBrush, RectF, Format)
        Format.Dispose()

    End Sub

    Private Sub DataGridComboBox_Enter(ByVal sender As Object, ByVal e As System.EventArgs)

        Dim dG As DataGrid = Me.DataGridTableStyle.DataGrid

        Me.cm = CType(dG.BindingContext(dG.DataSource, dG.DataMember), CurrencyManager)

        'Prevent combo from setting to list position 0 on enter
        If MyBase.GetColumnValueAtRow(cm, cm.Position) Is DBNull.Value Then
            Me.Combo.SelectedIndex = -1
        End If

    End Sub

    Private Sub DataGridComboBox_Leave(ByVal sender As Object, ByVal e As System.EventArgs)

        If InEdit Then
            If Me.Combo.SelectedIndex > -1 And cm.Position > -1 Then
                SetColumnValueAtRow(cm, cm.Position, Me.Combo.SelectedValue)
            End If
            EndEdit()
        End If

        HideComboBox()
        RaiseEvent Leave()
    End Sub

    Public Sub SetValue(ByVal value As Object)
        If InEdit Then
            If Me.Combo.SelectedIndex > -1 And cm.Position > -1 Then
                SetColumnValueAtRow(cm, cm.Position, Me.Combo.SelectedValue)
            End If
            EndEdit()
        Else
            SetColumnValueAtRow(cm, cm.Position, value)
        End If

        Me.Combo.SelectedValue = value

        HideComboBox()
        RaiseEvent Leave()
    End Sub

    Private Sub DataGridComboBox_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs)

        If Char.IsLetterOrDigit(e.KeyChar) Then
            InEdit = True
            MyBase.ColumnStartedEditing(Me.Combo)
            'Handle the optional autoDropDownOnEdit setting
            If mDropDown Then
                If Not Me.Combo.DroppedDown Then
                    Me.Combo.DroppedDown = True
                End If
            End If
        End If

    End Sub

    Private Sub Combo_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Combo.SelectedIndexChanged
        InEdit = True
        MyBase.ColumnStartedEditing(Me.Combo)
    End Sub

    Private Sub Combo_DataSourceChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Combo.DataSourceChanged
        If TypeOf (Me.Combo.DataSource) Is DataTable Then
            Me.dV = CType(Me.Combo.DataSource, DataTable).DefaultView
        ElseIf TypeOf (Me.Combo.DataSource) Is DataView Then
            Me.dV = CType(Me.Combo.DataSource, DataView)
        Else
            Dim i As Integer = -1
        End If

    End Sub

    Private Sub Combo_SelectedValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Combo.SelectedValueChanged
        RaiseEvent SelectedValue_Changed(sender, e)
    End Sub
End Class
Wow, thanks, I will try it out.  Thanks again
Thanks