I have a little problem with a data grid combo box control I've created (copied from examples found on the web). When the control is the first column in the data grid the combo box is created and opened empty and seems to struggle with the leave event.
The code is below, any ideas what I need to add or what I'm doing wrong?
The code is below, any ideas what I need to add or what I'm doing wrong?
Code:
Public Class DataGridComboBoxColumn
Inherits System.Windows.Forms.DataGridTextBoxColumn
#Region "Combo box code"
'Declare a combo box
Private WithEvents CellCombo As New Windows.Forms.ComboBox
'Provide a read-only property to access the combo box
Public ReadOnly Property ComboBox() As Windows.Forms.ComboBox
Get
Return CellCombo
End Get
End Property
'Set the value of the combo box
Private Sub SetComboValue()
Me.CellCombo.SelectedValue = MyBase.GetColumnValueAtRow( _
Me.CurrentEditingRow.Source, Me.CurrentEditingRow.RowNum)
End Sub
'Provide an event handler for whenever the combo box loses focus
Private Sub CellCombo_Leave(ByVal sender As Object, ByVal e As System.EventArgs) Handles CellCombo.Leave
'Set the value of the text box to match the value member of the combo box
If Not Me.CellCombo.SelectedValue Is Nothing Then
Me.SetColumnValueAtRow(Me.CurrentEditingRow.Source, _
Me.CurrentEditingRow.RowNum, _
Me.CellCombo.SelectedValue)
End If
'Remove the combobox from the datagrid
Try
Me.DataGridTableStyle.DataGrid.Controls.Remove(Me.CellCombo)
Catch ex As SystemException
System.Windows.Forms.MessageBox.Show(ex.Message)
End Try
'Paint the text
Dim bounds As New System.Drawing.Rectangle(Me.TextBox.Location.X, _
Me.TextBox.Location.Y, _
Me.TextBox.Width, _
Me.TextBox.Height)
MyBase.PaintText(Me.TextBox.CreateGraphics, bounds, _
Me.CellCombo.Text, False)
End Sub
#End Region
#Region "Editing row class"
'Declare an editing row class to hold the values when the edit method is run
Private Class CurrentRow
'Declare a source variable
Public Source As System.Windows.Forms.CurrencyManager
Public RowNum As Integer
Public Bounds As System.Drawing.Rectangle
Public IsReadOnly As Boolean
Public InstantText As String
Public IsCellVisible As Boolean
Public Sub New(ByVal source As System.Windows.Forms.CurrencyManager, _
ByVal rowNum As Integer, _
ByVal bounds As System.Drawing.Rectangle, _
ByVal [readOnly] As Boolean, _
ByVal instantText As String, _
ByVal cellIsVisible As Boolean)
'Set the values
Me.Source = source
Me.RowNum = rowNum
Me.Bounds = bounds
Me.IsReadOnly = [readOnly]
Me.InstantText = instantText
Me.IsCellVisible = cellIsVisible
End Sub
End Class
'Declare a CurrentRow variable to hold the details
Dim CurrentEditingRow As DocumentManager.DataGridComboBoxColumn.CurrentRow
#End Region
#Region "Initializing code"
'A vanilla new method
Public Sub New()
'Call the new method of the base class
MyBase.New()
End Sub
Public Sub New(ByVal ComboDataSet As System.Data.DataSet, _
ByVal TableName As System.String, _
ByVal ComboValueMember As System.String, _
ByVal ComboDisplayMember As System.String, _
ByVal IsDropDownListStyle As Boolean)
'Call the vanilla new method
Me.New()
'Establish the data binding
Me.CellCombo.DataSource = ComboDataSet.Tables(TableName)
Me.CellCombo.ValueMember = ComboValueMember
Me.CellCombo.DisplayMember = ComboDisplayMember
'Set the style of the drop down box
If IsDropDownListStyle Then
Me.CellCombo.DropDownStyle = ComboBoxStyle.DropDownList
Me.ReadOnly = True
Else
Me.CellCombo.DropDownStyle = ComboBoxStyle.DropDown
End If
End Sub
Public Sub New(ByVal ComboDataTable As System.Data.DataTable, _
ByVal ComboValueMember As System.String, _
ByVal ComboDisplayMember As System.String, _
ByVal IsDropDownListStyle As Boolean)
'Call the vanilla new method
Me.New()
'Establish the data binding
Me.CellCombo.DataSource = ComboDataTable
Me.CellCombo.ValueMember = ComboValueMember
Me.CellCombo.DisplayMember = ComboDisplayMember
'Set the style of the drop down box
If IsDropDownListStyle Then
Me.CellCombo.DropDownStyle = ComboBoxStyle.DropDownList
Me.ReadOnly = True
Else
Me.CellCombo.DropDownStyle = ComboBoxStyle.DropDown
End If
End Sub
#End Region
#Region "Overrides methods and functions"
Protected Overrides Sub Abort(ByVal rowNum As Integer)
MyBase.Abort(rowNum)
End Sub
Protected Overrides Function Commit(ByVal dataSource As System.Windows.Forms.CurrencyManager, _
ByVal rowNum As Integer) As Boolean
Return MyBase.Commit(dataSource, rowNum)
End Function
Protected Overloads Overrides Sub Edit(ByVal source As System.Windows.Forms.CurrencyManager, _
ByVal rowNum As Integer, _
ByVal bounds As System.Drawing.Rectangle, _
ByVal [readOnly] As Boolean, _
ByVal instantText As String, _
ByVal cellIsVisible As Boolean)
'This method is called when the cell becomes active.
'Suspend painting until all is set
Me.BeginUpdate()
'Start by calling the base Edit method
MyBase.Edit(source, rowNum, bounds, [readOnly], instantText, cellIsVisible)
'Make the textbox invisible
Me.TextBox.Visible = False
'Make the combo box visible
Me.CellCombo.Visible = True
'Set the boundary of the combobox
Me.CellCombo.Size = Me.TextBox.Size
'Set the position of the combobox
Me.CellCombo.SetBounds(bounds.X, bounds.Y, bounds.Width, bounds.Height)
'Add the combo box to the datagrid
Me.DataGridTableStyle.DataGrid.Controls.Add(Me.CellCombo)
'Create a new current editing row variable and set the values
Me.CurrentEditingRow = New DocumentManager.DataGridComboBoxColumn.CurrentRow( _
source, rowNum, bounds, [readOnly], _
instantText, cellIsVisible)
'Set the selected value of the combo box
Me.SetComboValue()
'Paint the changes
Me.EndUpdate()
End Sub
Protected Overrides Function GetColumnValueAtRow(ByVal source As System.Windows.Forms.CurrencyManager, _
ByVal rowNum As Integer) As Object
'Get the value at the column row from the base object
Dim ColumnValue As Object
ColumnValue = MyBase.GetColumnValueAtRow(source, rowNum)
'Create a temporary data table to hold the data table of the combo box
Dim dataTable As System.Data.DataTable
dataTable = CType(Me.CellCombo.DataSource, System.Data.DataTable)
'Loop through the rows of the data table to find the row with the
'correct selected value and return the display value
Dim rowIndex As Integer
If Not ColumnValue Is System.DBNull.Value Then
For rowIndex = 0 To (dataTable.Rows.Count - 1)
If dataTable.Rows(rowIndex).Item(Me.CellCombo.ValueMember) = _
CType(ColumnValue, String) Then
Return dataTable.Rows(rowIndex).Item(Me.CellCombo.DisplayMember)
Exit For
End If
Next
End If
End Function
Protected Overrides Function GetMinimumHeight() As Integer
'Return the minimum height of the base class or the combo box
If Me.ComboBox.Height > MyBase.GetMinimumHeight Then
Return Me.ComboBox.Height
Else
Return MyBase.GetMinimumHeight
End If
End Function
Protected Overrides Function GetPreferredHeight(ByVal g As System.Drawing.Graphics, _
ByVal value As Object) As Integer
'Return the preffered height of the base class or the height of
'the combo box
If Me.ComboBox.Height > MyBase.GetPreferredHeight(g, value) Then
Return Me.ComboBox.Height
Else
Return MyBase.GetPreferredHeight(g, value)
End If
End Function
Protected Overrides Function GetPreferredSize(ByVal g As System.Drawing.Graphics, _
ByVal value As Object) As System.Drawing.Size
'Return the preffered size of the base class
Return MyBase.GetPreferredSize(g, value)
End Function
Protected Overloads Overrides Sub Paint(ByVal g As System.Drawing.Graphics, _
ByVal bounds As System.Drawing.Rectangle, _
ByVal source As System.Windows.Forms.CurrencyManager, _
ByVal rowNum As Integer)
'Call the base paint method
MyBase.Paint(g, bounds, source, rowNum)
End Sub
Protected Overloads Overrides Sub Paint(ByVal g As System.Drawing.Graphics, _
ByVal bounds As System.Drawing.Rectangle, _
ByVal source As System.Windows.Forms.CurrencyManager, _
ByVal rowNum As Integer, _
ByVal alignToRight As Boolean)
'Call the base paint method
MyBase.Paint(g, bounds, source, rowNum, alignToRight)
End Sub
#End Region
End Class