我的部分代码在tabcontrol中创建了一个标签,然后用datagridview填充它,其中包含几个DataGridViewComboBoxColumn列。
看起来像这样:
Private Sub NewTabPage()
Dim TabPageCount As Integer = RacerOrderTAB.TabPages.Count
RacerOrderTAB.TabPages.Add(TeamNames(TabPageCount)) 'teamnames() is an array of team names
Dim CurrentTabPage = RacerOrderTAB.TabPages(TabPageCount)
Dim GridToAdd As New DataGridView
GridToAdd.Size = CurrentTabPage.Size
GridToAdd.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
GridToAdd.Location = New Point(CurrentTabPage.Location.X, CurrentTabPage.Location.Y)
GridToAdd.Columns.Add("ShiftCOL", "Shift Name")
GridToAdd.Name = "grid_" & CurrentTabPage.Text
For y As Integer = 1 To ShiftSetup.racerspershift 'add extra column for each racer in shift
Dim cmb As New DataGridViewComboBoxColumn
cmb.HeaderText = "Racer" & y
cmb.Name = "Racer_" & y
cmb.MaxDropDownItems = AmountOfRacers
cmb.DisplayStyle = DataGridViewComboBoxDisplayStyle.DropDownButton
GridToAdd.Columns.Add(cmb)
Next
RacerOrderTAB.TabPages(TabPageCount).Controls.Add(GridToAdd)
End Sub
但是我一直难以为组合框添加一个事件处理程序。我想要发生的是,当点击并打开组合框时,我用我想要的项目填充它。 我设法隐约地通过添加:
来实现它AddHandler GridToAdd.EditingControlShowing, AddressOf <sub name>
然后一直无法弄清楚点击了哪个组合框,以及如何填充它。在下拉列表出现之前,还需要四次点击。我只是有点困惑。
感谢您的任何建议;这些DataGridViewComboBoxColumns [深呼吸]让我很困惑!
答案 0 :(得分:1)
它可能有点hacky但它应该做你要求的...希望。我创建了两个List(Of String)
个变量。 AllRacers
包含所有参赛者...即我们想要出现在组合框中的所有名称,使得该行上没有其他组合框选择了一个项目。这些名称是所有行上的所有组合框最初将包含在可选项列表中的内容。
其他List(Of String)
UsedRacers
包含当前行中所有选定项目的“组合框”列表。每次更改单元格值并且它是“组合框”列单元格之一时,将清除/更新UsedRacers
以反映当前行上添加/更改的所选项目。
更改“comboBox”单元格值时,会调用SetUsedRacersForRow
...
Private Sub SetUsedRacersForRow(rowIndex As Int16)
UsedRacers.Clear()
Dim curValue = ""
For i = 1 To racersPerShift
If (Not (dgvRacers.Rows(rowIndex).Cells(i).Value Is Nothing)) Then
curValue = dgvRacers.Rows(rowIndex).Cells(i).Value.ToString()
If (Not (String.IsNullOrEmpty(curValue))) Then
UsedRacers.Add(curValue)
End If
End If
Next
End Sub
上面的代码循环遍历给定行中的所有“组合框”单元格,如果“组合框”单元格中选择了某些内容,则所选值将添加到UsedRacers
列表中。
现在,该行中所有“组合框”的选定项目都在UsedRacers
列表中,我们现在可以遍历该行中的每个“组合框”单元格并设置正确的名称列表。为了提供帮助,创建了一个返回DataGridViewComboBoxCell
的方法,以便当前UsedRacers
列表中的名称不会出现在DataGridViewComboBoxCell
的可选名称列表中。
此处唯一的问题是当前已选择项目的单元格。具有所选项目的每个“组合框”单元将唯一地需要在其项目列表中具有其所选项目。要解决此问题,需要检查“combobox”单元格是否包含值。如果“组合框”单元格包含选定值,则该值也包含在UsedRacers
列表中。由于THIS单元格是UseRacers
列表中的单元格...然后我们需要将此值添加到此单元格项目列表中。否则,我们将无法显示唯一选择。
为了使UsedRacers
列表保持一致,我们需要将此项直接添加到单个“组合框”单元格中,而不是删除或更改UsedRacers
列表,因为这将用于其他“组合框” “ 细胞。换句话说......无论在组合框中选择了什么值,我们都需要确保它是“combobox”可选项列表中的项目之一。我希望这是有道理的。
这可以在DataGridViews
CellChanged
事件中完成。
Private Sub dgvRacers_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles dgvRacers.CellValueChanged
If (e.ColumnIndex >= 1 And e.ColumnIndex <= racersPerShift) Then
SetUsedRacersForRow(e.RowIndex)
For i = 1 To racersPerShift
Dim newCell As DataGridViewComboBoxCell = GetCurrentComboBoxCell()
If (Not (dgvRacers.Rows(e.RowIndex).Cells(i).Value Is Nothing)) Then
Dim curValue = dgvRacers.Rows(e.RowIndex).Cells(i).Value.ToString()
newCell.Items.Add(curValue)
newCell.Value = curValue
End If
dgvRacers.Rows(e.RowIndex).Cells(i) = newCell
Next
End If
End Sub
在上面的代码中,方法GetCurrentComboBoxCell
(下面)返回DataGridViewComboBoxCell
,以便项目组合框列表中的项目不包含UsedRacers
中的任何项目名单。因此,需要进行检查(上图)以查看单元格是否已包含值。注意:返回的DataGridViewComboBoxCell
将始终包含“空白”空项。这是必要的,允许用户“取消选择”任何当前选择的值,然后使“取消选择”项目可用于其他组合框单元格。
Public Function GetCurrentComboBoxCell() As DataGridViewComboBoxCell
Dim newComboCell = New DataGridViewComboBoxCell()
newComboCell.DisplayStyle = DataGridViewComboBoxDisplayStyle.DropDownButton
newComboCell.FlatStyle = FlatStyle.Flat
newComboCell.Items.Add("")
For Each curRacer In AllRacers
If (Not UsedRacers.Contains(curRacer)) Then
newComboCell.Items.Add(curRacer)
End If
Next
Return newComboCell
End Function
最后,把所有这些放在一起......
Dim racersInShift = 3
Dim AllRacers As List(Of String) = New List(Of String) From {"John", "Bobby", "Trent", "Josh", "Chapman", "Henry", "George", "Marvin"}
'Dim racersPerShift As Int16 = AllRacers.Count '<-- should be MAX value
Dim racersPerShift As Int16 = 4
Dim UsedRacers = New List(Of String)
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
BuildGrid()
End Sub
Private Sub BuildGrid()
dgvRacers.Size = New Size(800, 200)
dgvRacers.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
'dgvRacers.Location = New Point(50, 200)
dgvRacers.Columns.Add("ShiftCOL", "Shift Name")
dgvRacers.Name = "RacersDGV"
dgvRacers.EditMode = DataGridViewEditMode.EditOnEnter
dgvRacers.AllowUserToAddRows = False
AddRacerColumns()
AddRacerRows()
End Sub
Private Sub AddRacerColumns()
Dim newColumn As DataGridViewComboBoxColumn
For i As Integer = 1 To racersPerShift
newColumn = GetNewComboBoxColumn("Racer" & i, "Racer " & i)
dgvRacers.Columns.Add(newColumn)
Next
End Sub
Private Sub AddRacerRows()
For i As Integer = 1 To racersInShift
Dim row As New DataGridViewRow
dgvRacers.Rows.Add(row)
Next
End Sub
Private Sub dgvRacers_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs)
‘See code above
End Sub
Private Sub SetUsedRacersForRow(rowIndex As Int16)
‘See code above
End Sub
Public Function GetCurrentComboBoxCell() As DataGridViewComboBoxCell
‘See code above
End Function
‘Lastly a method to set a whole `DataGridviewComboBoxColumn` which is used to initialize all the combo box columns
Public Function GetNewComboBoxColumn(colName As String, colHeader As String) As DataGridViewComboBoxColumn
Dim newComboCol = New DataGridViewComboBoxColumn()
newComboCol.DisplayStyle = DataGridViewComboBoxDisplayStyle.DropDownButton
newComboCol.FlatStyle = FlatStyle.Flat
newComboCol.Items.Add("")
newComboCol.HeaderText = colHeader
newComboCol.Name = colName
For Each curRacer In AllRacers
newComboCol.Items.Add(curRacer)
Next
Return newComboCol
End Function
我希望这会有所帮助,我猜测有一种更简单的方法可以做到这一点。