I have a DataGridView
which contains, among other things, a "Feature" column and a "Value" column. The "Feature" column is a DataGridViewComboBoxColumn
. What I would like to do, is manipulate the "Value" column, such that it can be one of a number of controls, depending on the item selected in the "Feature" column on any given row. So, for example :
Feature | Value Cell Behaviour |
---|---|
A | Combobox with a pre-determined set of options, specific to Feature A |
B | Combobox with a different set of pre-determined options, specific to Feature B |
C | Checkbox |
D | Textbox (free-format) |
X | etc. etc. |
My initial naive approach to this (which I never really expected to work but figured I'd try anyway...) was to programmatically manipulate the specific value cell in the grid whenever the Feature combobox on the same row was changed :
Private Sub dgv_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles dgv.CellValueChanged
Dim changedCell As DataGridViewCell = CType(dgv.Rows(e.RowIndex).Cells(e.ColumnIndex), DataGridViewCell)
If changedCell.ColumnIndex = cboFeatureColumn.Index Then
Dim cboChangedFeature = CType(changedCell, DataGridViewComboBoxCell)
If cboChangedFeature.Value IsNot Nothing Then ConfigureValueField(cboChangedFeature)
End If
End Sub
Private Sub ConfigureValueField(cboFeature As DataGridViewComboBoxCell)
Dim cllValueField As DataGridViewCell = dgv.Rows(cboFeature.RowIndex).Cells(valueColumn.Index)
Dim featureID As Integer = dgv.Rows(cboFeature.RowIndex).Cells(featureIDColumn.Index).Value
Dim matches = From row In dtbFeatureList Let lookupID = row.Field(Of Integer)("ID") Where lookupID = featureID
Dim strFieldControl As String = ""
If matches.Any Then strFeatureControl = matches.First().row.Field(Of String)("FieldControl")
Select Case strFieldControl
Case "Checkbox"
' Do something
Case "Textbox"
' Do something
Case "Combobox"
Dim cboConfigured As New DataGridViewComboBoxCell
Dim dvOptions As New DataView(dtbFeatureValueList)
dvOptions.RowFilter = "[FeatureID] = " & featureID
Dim dtbOptions As DataTable
dtbOptions = dvOptions.ToTable
With cboConfigured
.DataSource = dtbOptions
.ValueMember = "Value"
.DisplayMember = "ValueText"
.DisplayStyle = DataGridViewComboBoxDisplayStyle.ComboBox
.ReadOnly = False
End With
cllValueField = cboConfigured
End Select
End Sub
But this (probably, obviously to many) doesn't work; for starters it throws a DataError Default Error Dialog :
The following exception occurred in the DataGridView: System.FormatException: DataGridViewComboBoxCell value is not valid To replace this default dialog please handle the DataError event.
...which I can trap and handle (i.e. ignore!) easily enough :
Private Sub dgv_DataError(sender As Object, e As DataGridViewDataErrorEventArgs) Handles dgv.DataError
e.Cancel = True
End Sub
...and the resulting cell does have the appearance of a combobox but nothing happens when I click the dropdown (no list options appear) I suspect there are a whole host of DataErrors being thrown; to be quite honest, I'm not entirely comfortable with ignoring exceptions like this without handling them properly...
The only alternative option I can think of is to add separate columns for each possible value type (so add a DataGridViewComboBoxColumn
for combos, a DataGridViewCheckBoxColumn
for checkboxes, a DataGridViewTextBoxColumn
for textboxes etc.) but then all of my values are scattered across multiple columns instead of all under a single heading which will be really confusing to look at.
And I really want to retain the appearance of comboboxes (set list of options) versus checkboxes (boolean values) versus textboxes (free-format text), as it makes it a lot easier for users to differentiate the values.
I read somewhere that it may be possible to derive my own custom column class, inheriting the native DataGridViewColumn
class, but I couldn't find any examples of how this was done. I've done something similar with a customised DataGridViewButtonColumn
but literally just to change the appearance of the buttons across the entire column, not the functionality of the individual cells within it.
Would anybody have any suggestions as to how it might be possible to have a mix of controls in the same column, configured specifically to the row in which they reside?
EDIT