VB.NET 如何将事件处理程序添加到位于以编程方式创建的控件中的 ComboBoxColumn?
VB.NET How to add Event Handler to ComboBoxColumn located in programmatically created controls?
我的部分代码在 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 [深呼吸] 让我很困惑!
它可能有点老套,但它应该可以满足您的要求……希望如此。我创建了两个 List(Of String)
变量。 AllRacers
包含所有赛车手……即我们希望出现在组合框中的所有名称,以便该行上没有其他组合框选择了一个项目。这些名称是所有行上的所有组合框最初包含在可选项目列表中的名称。
另一个 List(Of String)
UsedRacers
包含当前行上所有已选择项目的“组合框”的列表。每次更改单元格值并且它是“组合框”列单元格之一时,UsedRacers
是 cleared/updated 以反映当前行上的 added/changed 所选项目。
当“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
列表中,我们现在可以遍历该行中的每个“组合框”单元格并设置正确的名称列表。为了提供帮助,创建了一个 returns 和 DataGridViewComboBoxCell
的方法,这样当前 UsedRacers
列表中的名称将不会出现在 DataGridViewComboBoxCell
的可选名称列表中。
这里唯一的问题是当前选择了项目的单元格。每个选择了项目的“组合框”单元格都需要在其项目列表中包含其选择的项目。为了解决这个问题,需要检查“组合框”单元格是否包含值。如果“组合框”单元格包含选定值,则该值也包含在 UsedRacers
列表中。由于此单元格是 UseRacers
列表中的单元格……因此我们需要将此值添加到此单元格项目列表中。否则,我们将无法显示唯一选择。
为了保持 UsedRacers
列表的一致性,我们需要将此项目直接添加到单个“组合框”单元格中,而不是删除或更改 UsedRacers
列表,因为这将用于另一个“组合框”单元格。换句话说......无论在组合框中选择什么值,我们都需要确保它是“组合框”可选项目列表中的项目之一。我希望这是有道理的。
这些都可以在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
(下面)returns一个DataGridViewComboBoxCell
使得组合框项目列表中的项目不包含任何项目UsedRacers
列表。因此,需要检查(上图)以查看单元格是否已包含值。注意:返回的 DataGridViewComboBoxCell
将始终包含一个“空白”的空项目。这是必要的,以允许用户“De-Select”任何当前选择的值,然后使“De-Selected”项目可用于其他组合框单元格。
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
希望这对您有所帮助,我想有更简单的方法可以做到这一点。
我的部分代码在 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 [深呼吸] 让我很困惑!
它可能有点老套,但它应该可以满足您的要求……希望如此。我创建了两个 List(Of String)
变量。 AllRacers
包含所有赛车手……即我们希望出现在组合框中的所有名称,以便该行上没有其他组合框选择了一个项目。这些名称是所有行上的所有组合框最初包含在可选项目列表中的名称。
另一个 List(Of String)
UsedRacers
包含当前行上所有已选择项目的“组合框”的列表。每次更改单元格值并且它是“组合框”列单元格之一时,UsedRacers
是 cleared/updated 以反映当前行上的 added/changed 所选项目。
当“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
列表中,我们现在可以遍历该行中的每个“组合框”单元格并设置正确的名称列表。为了提供帮助,创建了一个 returns 和 DataGridViewComboBoxCell
的方法,这样当前 UsedRacers
列表中的名称将不会出现在 DataGridViewComboBoxCell
的可选名称列表中。
这里唯一的问题是当前选择了项目的单元格。每个选择了项目的“组合框”单元格都需要在其项目列表中包含其选择的项目。为了解决这个问题,需要检查“组合框”单元格是否包含值。如果“组合框”单元格包含选定值,则该值也包含在 UsedRacers
列表中。由于此单元格是 UseRacers
列表中的单元格……因此我们需要将此值添加到此单元格项目列表中。否则,我们将无法显示唯一选择。
为了保持 UsedRacers
列表的一致性,我们需要将此项目直接添加到单个“组合框”单元格中,而不是删除或更改 UsedRacers
列表,因为这将用于另一个“组合框”单元格。换句话说......无论在组合框中选择什么值,我们都需要确保它是“组合框”可选项目列表中的项目之一。我希望这是有道理的。
这些都可以在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
(下面)returns一个DataGridViewComboBoxCell
使得组合框项目列表中的项目不包含任何项目UsedRacers
列表。因此,需要检查(上图)以查看单元格是否已包含值。注意:返回的 DataGridViewComboBoxCell
将始终包含一个“空白”的空项目。这是必要的,以允许用户“De-Select”任何当前选择的值,然后使“De-Selected”项目可用于其他组合框单元格。
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
希望这对您有所帮助,我想有更简单的方法可以做到这一点。