我有一个带有两个文本框列和一个组合框列的datagridview。组合框的DataSource绑定到下拉列表值的枚举。 datagridview的DataSource绑定到一个自定义类,其数据类型为string,string和enum。
前两列预先填充了值,在第三列中,用户必须从下拉列表中选择一个值。到目前为止,所有这一切都很出色,除了......
组合框字段应该是一对一的映射,这意味着没有两个组合框应该具有相同的值。我真的不确定如何实现这种行为。是否应从剩余的下拉列表中删除所选值?如果选择的值保留在下拉列表中,并且只选择两个相同的值时会出错?
任何想法以及如何实施这些想法都会有很大帮助。
由于
note 可以多次使用的唯一可接受的值是“无”
答案 0 :(得分:1)
我有一个想法,可能会从剩余的下拉菜单中删除所选的值。
我有一个名为Runner
的类,它与您的示例有类似的设置。
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
我还有一个名为Result
的枚举,它将填入ComboBoxCell
:
Public Enum Result
None = 0
Bronze = 1
Silver = 2
Gold = 3
End Enum
当我创建数据对象并将它们绑定到DataGridView
时,我这样做(注意 - 放置是一个全局列表(结果),跑者是一个全局列表(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
现在,只要ComboBoxColumn
中的单元格值发生更改,就会从包含枚举的列表中删除新值:
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
在更改下拉选项时要小心......按照此Discussion,您必须在DataGridView
值更改后立即将ComboBox
设置为提交值。我从讨论中得到了答案并做了类似的事情:
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
最后,您要处理DataError
的{{1}}事件并将其留空,以便在从枚举列表中删除值时不会向您发送DataGridView
这可以让你大约90%的方式。更改值时,它不会将项重新添加到列表中。例如,如果我从Gold更改为Silver,则应将Gold添加回列表。您可以找出要处理的事件以获取旧值和新值,并根据枚举值将旧值插回到正确索引的列表中。
答案 1 :(得分:1)
我决定使用DataGridView的CellValidating事件来检查是否多次选择了相同的值。如果是,则在行标题列中显示错误消息。
错误组合框在错误解决之前不会失去焦点。
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