2

我有一个带有两个文本框列和一个组合框列的 datagridview。组合框的 DataSource 绑定到下拉列表值的枚举。datagridview 的 DataSource 绑定到一个自定义类,数据类型为字符串、字符串和枚举。

前两列预先填充了值,在第三列中,用户必须从下拉列表中选择一个值。到目前为止,所有这些都运行良好,除了......

组合框字段应该是一对一的映射,这意味着没有两个组合框应该具有相同的值。我真的不确定如何实现这种行为。是否应该从剩余的下拉列表中删除所选值?选择的值是否应该保留在下拉列表中,并且在选择两个相同的值时只给出错误?

任何想法以及如何实施这些想法都会有很大帮助。

谢谢

请注意,可以多次使用的唯一可接受的值是“无”

在此处输入图像描述

4

2 回答 2

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,我会这样做(注意 - Placements 是一个全局 List(Of Result) 并且 Runners 是一个全局 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

现在,每当单元格的值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

更改下拉选择时要小心...根据此讨论,您必须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事件DataGridView并将其留空,以免Exceptions在从枚举列表中删除值时被抛出。

这可以让你到达那里大约 90% 的路。当您更改值时,它不会将项目重新添加到列表中。例如,如果我从 Gold 更改为 Silver,Gold 应该重新添加到列表中。您可能可以弄清楚要处理哪些事件来获取旧值和新值,然后根据其枚举值将旧值插入到正确索引处的列表中。

于 2013-02-14T00:40:06.757 回答
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

在此处输入图像描述

于 2013-02-19T18:57:09.523 回答