Search code examples
vb.netwinformsdatagridviewdatagridcomboboxcolumn

VB.NET datagridview one-to-one mapping of combobox


I have a datagridview with two textbox columns and one combobox column. The combobox's DataSource is bound to enums for the values of the dropdown. The datagridview's DataSource is bound to a custom class with datatypes of string, string and enum.

The first two columns are pre-populated with values and in the third column the user must select a value from the dropdown. All this is working excellent so far except....

The combobox field should be a one-to-one kind of mapping, meaning no two comboboxes should have the same value. I am really not sure how to implement this kind of behavior. Should the chosen value be removed from the remaining dropdowns? should the chosen value remain in the dropdown and just give an error when two of the same are selected?

Any ideas and how to implement these ideas will be of great help.

Thanks

note the only acceptable value that can be used more than once is 'None'

enter image description here


Solution

  • I decided to use the CellValidating event of the DataGridView to check whether or not the same value is selected more than once. If it is then a error message is displayed in the row header column.

    The combobox in error will not lose focus until the error is resolved.

    Private Sub DataGridView1_CellValidating(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellValidatingEventArgs) Handles DataGridView1.CellValidating
    
        Dim headerText As String = DataGridView1.Columns(e.ColumnIndex).HeaderText
    
        'Abort validation if cell is not in the Mapping column. 
        If Not headerText.Equals("Column Mapping") Then Return
    
        'Clear error on current row.
        DataGridView1.Rows(e.RowIndex).ErrorText = Nothing
        e.Cancel = False
    
        Dim newMappingValue As XmlElement = DirectCast([Enum].Parse(GetType(XmlElement), e.FormattedValue), XmlElement)
    
        ' Abort validation if cell value equal XmlElement.None 
        If newMappingValue.Equals(XmlElement.None) Then Return
    
        For Each dgvRow As DataGridViewRow In DataGridView1.Rows
            Dim currentMappingValue As XmlElement = dgvRow.Cells.Item(headerText).Value
    
            If dgvRow.Index <> e.RowIndex Then
                If currentMappingValue.Equals(newMappingValue) Then
                    DataGridView1.Rows(e.RowIndex).ErrorText = "Value already selected, please select a different value."
                    e.Cancel = True
                End If
            End If
        Next
    
    End Sub
    

    enter image description here