我在WinForm
上有三个组合框,如下所示:
___________________________
ComboBox List 1: |_______________________|___|
___________________________
ComboBox List 2: |_______________________|___|
___________________________
ComboBox List 3: |_______________________|___|
这些组合框中的每一个都将在设计时具有" A"," B"," C"的列表。
默认情况下,列表1是表单上唯一活动的列表,列表2和列表3在其前任选择时将变为活动状态。
我想做的是,如果用户选择选项C,我希望选项C不再适用于列表2和3。
我知道这将涉及组合框的.SelectedIndexChanged
事件,但不知道从何处开始编码。
我在StackOverflow上找到了以下答案,我的情况并不适用,因为我是在设计时提供项目而不是通过导入文件:vb.net change combobox options depending on selected item in 2 previous comboboxes
答案 0 :(得分:2)
这与史蒂夫的答案类似,但使用DataSource
。此外,每个CBO都不需要Enable
/ Disable
。在进行更改时,会从源中过滤先前的选择。任何重复的“之前”更改都会被撤消。
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
由于cbo3仅限于未在#1或#2(奴隶)中挑选的项目,因此当选择更改时,您无需执行任何操作。
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)。这可能需要进行一些调整,因为对于跟进修订形式而言,它不在我的头顶:
' 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。它还会重置子/从/下一个选择中的先前选择。
答案 1 :(得分:1)
好吧,假设你的组合框命名为b1,b2和b3。所有这些组合都链接到相同的lists = []
for x in range(3):
for y in range(3):
if x!=y:
lists.append([x,y])
事件处理程序,并且(如您所说)您已将b1,b2和b3上的初始元素设置为固定的字符串列表。
现在你还应该将b2和b3的Enabled属性设置为false,让b1上的选择驱动你在SelectedIndexChanged事件中的逻辑
SelectedIndexChanged