这类似于史蒂夫的回答,但使用了DataSource。此外,没有真正需要Enable/Disable 每个 CBO。当他们进行更改时,先前的选择会从源中过滤掉。任何重复的“先前”更改都将被撤消。
CBO1 总是有完整的列表,而其他的则省略了之前的选择。您不能以重复选择结束,因为重新选择 #2 与 #3 相同,会将 #3 的内容更改为列表中的第一个选项。
' the master list
Private OptList As New List(Of String)
Private ignore As Boolean
' initialize somewhere:
OptList.AddRange(New String() {"Red", "Green", "Blue", "Violet", "Orange"})
' set up cbos
' ignore changes while setting up:
ignore = True
cb1.DataSource = OptList.ToArray
cb1.SelectedIndex = -1
cb2.DataSource = OptList.ToArray
cb2.SelectedIndex = -1
cb3.DataSource = OptList.ToArray
cb3.SelectedIndex = -1
ignore = False
全部启用后,他们可以按任意顺序选择它们。
Private Sub cbo_SelectedIndexChanged(sender As Object, e As EventArgs) _
Handles cb1.SelectedIndexChanged, cb2.SelectedIndexChanged
If ignore Then Exit Sub
Dim cbo = TryCast(sender, ComboBox)
If cbo IsNot Nothing AndAlso cbo Is cb1 Then
cb2.DataSource = GetFilteredList(New String() {cb1.Items(cb1.SelectedIndex)})
Else
cb3.DataSource = GetFilteredList(New String() {cb1.SelectedItem.ToString,
cb2.SelectedItem.ToString})
End If
End Sub
Private Function GetFilteredList(items As String()) As String()
Return OptList.Except(items).ToArray()
End Function
Since cbo3 is limited to those items not picked in #1 or #2 (a slave) you dont have to do anything when that selection changes.
Could this be expanded to say 9 cbo by continuing multiple if/else statements
和
How would I keep the first option. Say if I wanted to include a "None" option always available.
那么多,我会做的更抽象。代码可能更难阅读/遵循,但它的数量更少(我使用的是 4 个 cbos)。这可能需要一些调整,因为对于 follow up 修订表来说,这是我的想法:
' additional array to hold the CBOs involved
Private tgtCBOs As ComboBox()
...
' initialization:
OptList.AddRange(New String() {"(None)", "Red", "Green", "Blue", "Violet",
"Orange", "Mauve", "White"})
tgtCBOs = New ComboBox() {cb1, cb2, cb3, cb4}
' set initial index to 0 with a default item
Private Sub cb2_SelectedIndexChanged(sender As Object, e As EventArgs) Handles _
cb2.SelectedIndexChanged, cb1.SelectedIndexChanged, cb3.SelectedIndexChanged
If ignore Then Exit Sub
Dim cbo = TryCast(sender, ComboBox)
' identify which one this is
Dim ndx = Array.IndexOf(tgtCBOs, cbo)
' get all the selections from 0 to here
Dim exclude = GetExclusionList(ndx)
' remove excludes from the NEXT cbo
Dim newList As New List(Of String)
If ndx + 1 < tgtCBOs.Length Then
newList = OptList.Except(exclude).ToList()
If newList(0) <> OptList(0) Then newList.Insert(0, "(None)")
tgtCBOs(ndx + 1).DataSource = newList.ToArray()
End If
End Sub
Private Function GetExclusionList(ndx As Int32) As List(Of String)
Dim exclude As New List(Of String)
For n As Int32 = 0 To ndx
If tgtCBOs(n).SelectedIndex <> -1 Then
exclude.Add(tgtCBOs(n).Items(tgtCBOs(n).SelectedIndex).ToString())
End If
Next
Return exclude
End Function
请注意,最后一个 cbo 没有连接到该处理程序,因为它没有 "slave" 。如果您需要响应事件,请将其连接到自己的处理程序。
此外,为“下一个”重置DataSource(或清除项目)的行为将导致该事件为下一个/子/从 CBO 触发。因此,对 CBO2 的更改将触发 3、4、5..n 的事件。它还会重置子/从/下一个中的先前选择。