I have an idea based off your intent to possibly remove the chosen value from the remaining dropdowns.
I have a class called Runner
which has a similar setup to your example.
Public Class Runner
Public Property FirstName As String
Public Property LastName As String
Public Property Placement As Result
Public Sub New(fn As String, ln As String)
FirstName = fn
LastName = ln
Placement = Result.None
End Sub
End Class
I also have an enum called Result
which will get populated into the ComboBoxCell
:
Public Enum Result
None = 0
Bronze = 1
Silver = 2
Gold = 3
End Enum
When I create data objects and bind them to the DataGridView
, I do so like this (note - Placements is a global List(Of Result) and Runners is a global List(Of Runner):
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Placements.Add(Result.None)
Placements.Add(Result.Bronze)
Placements.Add(Result.Silver)
Placements.Add(Result.Gold)
Runners.Add(New Runner("John", "Smith"))
Runners.Add(New Runner("Jane", "Doe"))
Runners.Add(New Runner("Bill", "Jones"))
Column1.DataPropertyName = "FirstName"
Column2.DataPropertyName = "LastName"
Column3.DataPropertyName = "Placement"
Column3.DataSource = Placements
DataGridView1.DataSource = Runners
End Sub
Now, whenever the value of a cell in the ComboBoxColumn
changes, you remove the new value from the list that contains the enums:
Private Sub DataGridView1_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellValueChanged
If (e.RowIndex > -1 And e.ColumnIndex = 2) Then
Dim currentvalue As Result = DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value
If currentvalue <> Result.None Then
Placements.Remove(currentvalue)
End If
End If
End Sub
Be careful when changing drop down selections... as per this Discussion, you have to trick the DataGridView
into committing values as soon as the ComboBox
value changes. I used an answer from that discussion and did something like this:
Private Sub DataGridView1_CurrentCellDirtyStateChanged(sender As Object, e As EventArgs) Handles DataGridView1.CurrentCellDirtyStateChanged
Dim col As DataGridViewColumn = DataGridView1.Columns(DataGridView1.CurrentCell.ColumnIndex)
If col.Name = "Column3" Then
DataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit)
Dim selected As DataGridViewCell = DataGridView1.CurrentCell
DataGridView1.CurrentCell = Nothing //This line and the next one simply hide
DataGridView1.CurrentCell = selected //an odd display effect that occurs
//because we remove a value and change the
//selection at the same time
End If
End Sub
Finally, you want to handle the DataError
event for the DataGridView
and leave it blank so that you don't get Exceptions
thrown at you when removing values from your list of enums.
This gets you about 90% of the way there. It will not re-add items to the list when you change a value. For example if I change from Gold to Silver, Gold should be added back to the list. You can probably figure out what events to handle to get the old value and the new one, and insert the old value back into the list at the correct index based on its enum value.