Vb.net 删除或禁用在其他列表中选择的组合框项目

Vb.net 删除或禁用在其他列表中选择的组合框项目,vb.net,winforms,combobox,Vb.net,Winforms,Combobox,我在WinForm上有三个组合框,如下所示: ___________________________ ComboBox List 1: |_______________________|___| ___________________________ ComboBox List 2: |_______________________|___| _______________________

我在
WinForm
上有三个组合框,如下所示:

                  ___________________________
ComboBox List 1: |_______________________|___|
                  ___________________________
ComboBox List 2: |_______________________|___|
                  ___________________________
ComboBox List 3: |_______________________|___|
在设计时,每个组合框都有一个“a”、“B”、“C”列表

默认情况下,列表1是表单上唯一处于活动状态的列表,列表2和列表3将在其前一个列表被选择时变为活动状态

我想做的是,如果用户选择选项C,我希望选项C不再适用于列表2和3

我知道这将涉及组合框的
.SelectedIndexChanged
事件,但不知道从何处开始编码


我在StackOverflow上找到了以下答案,我的情况如何不适用,因为我在设计时提供项目,而不是通过导入文件:

好吧,假设您的组合框命名为b1、b2和b3。所有这些组合都链接到相同的
SelectedIndexChanged
eventhandler,并且(如您所说)您已经将b1、b2和b3上的初始元素设置为固定的字符串列表

现在,您还应该将b2和b3的Enabled属性设置为false,并让b1上的选择驱动SelectedIndexChanged事件中的逻辑

Sub onIndexChanged(sender As Object, e As EventArgs)
    Dim b As ComboBox = CType(sender, System.Windows.Forms.ComboBox)
    If b.Equals(b1) Then
        If b1.SelectedIndex = -1 Then

            b2.Enabled = False
            b3.Enabled = False
        Else
            b2.Enabled = True
            b3.Enabled = False
            b2.Items.Clear()
            b3.Items.Clear()
            b2.Items.AddRange(b1.Items.Cast(Of String)() _
             .Where(Function(x) x <> b1.SelectedItem.ToString()).ToArray())
        End If
    Else if b.Equals(b2) Then
        If b2.SelectedIndex <> -1 Then

            b3.Items.Clear()
            b3.Items.AddRange(b2.Items.Cast(Of String)(). _
                Where(Function(x) x <> b2.SelectedItem.ToString()).ToArray())
            b3.Enabled = True
            b3.SelectedIndex = 0
        End If 
    End If 
End Sub
Sub-onIndexChanged(发送方作为对象,e作为事件参数)
Dim b As ComboBox=CType(发送方,System.Windows.Forms.ComboBox)
如果b等于(b1),那么
如果b1.SelectedIndex=-1,则
b2.已启用=错误
b3.Enabled=False
其他的
b2.已启用=真
b3.Enabled=False
b2.Items.Clear()
b3.Items.Clear()
b2.Items.AddRange(b1.Items.Cast(字符串)()_
.Where(函数(x)x b1.SelectedItem.ToString()).ToArray())
如果结束
否则,如果b等于(b2),则
如果b2.1选择了索引-1,则
b3.Items.Clear()
b3.Items.AddRange(b2.Items.Cast(字符串的)()_
其中(函数(x)x b2.SelectedItem.ToString()).ToArray())
b3.启用=真
b3.SelectedIndex=0
如果结束
如果结束
端接头

这与Steve的答案类似,但使用了一个
数据源。此外,实际上不需要启用每个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
由于cbo3仅限于未在#1或#2(从属)中拾取的项目,因此当选择更改时,您无需执行任何操作



是否可以通过继续执行多个if/else语句将其扩展为9 cbo
如何保留第一个选项。假设我想包括一个始终可用的“无”选项。

如果有那么多,我会做得更抽象一些。代码可能更难阅读/理解,但内容较少(我使用的是4个CBO)。这可能需要一些调整,因为对于后续修订的表单,它已经超出了我的脑海:

' 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的附加阵列
专用tgtCBOs作为组合框()
...
'初始化:
AddRange(新字符串(){“(无)”、“红色”、“绿色”、“蓝色”、“紫色”,
“橙色”、“淡紫色”、“白色”})
tgtCBOs=新组合框(){cb1,cb2,cb3,cb4}
'使用默认项将初始索引设置为0
私有子cb2\u SelectedIndexChanged(发送方作为对象,e作为事件参数)处理\u
cb2.SelectedIndexChanged,cb1.SelectedIndexChanged,cb3.SelectedIndexChanged
如果忽略,则退出Sub
Dim cbo=TryCast(发送方,组合框)
“确定这是哪一个
Dim ndx=Array.IndexOf(tgtCBOs、cbo)
'获取从0到此处的所有选择
Dim exclude=GetExclutionList(ndx)
'从下一个cbo中删除排除项
将新列表变暗为新列表(字符串)
如果ndx+1
请注意,最后一个cbo没有连接到该处理程序,因为在那里它没有“从属”。如果需要响应事件,请将其连接到自己的处理程序


此外,为“下一个”重置
数据源
(或为此清除项目)的行为将导致下一个/子/从CBO触发该事件。因此,改变CBO2将触发事件3、4、5..n。它还会重置子/从/下一个选项中的上一个选项。

是否可以通过继续多个if/else语句将其扩展为9 cbo?好的。。。第二种选择有效!只有一个小问题。我如何保留第一个选项。比如说,如果我想包含一个始终可用的“无”选项。我看不出如何保留一个选项……就是这样……前几天我一直在寻找答案。我对Q或A的记忆不足,无法找到它,因为它们是对象,只有当它们引用相同的对象时,才能进行测试。它们用途广泛,所以可以用很多方法,但通常我会比较它们的价值<代码>如果nvp1.值nvp2.值,则…
。原因是类似{“钚”,94}的值通常是重要部分,名称为人类可读/可理解的版本。但也有可能是另一种情况(Value==名称的某个索引}。该版本非常简单-您可以使用自定义比较器(app)对其进行增强