删除或禁用在另一个列表中选择的ComboBox项

时间:2016-01-16 14:58:42

标签: vb.net winforms combobox

我在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

2 个答案:

答案 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 statementsHow 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
相关问题