You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET中如何根据下拉框选择移除后续下拉框的重复选项?

问题:ASP.NET多DropDownList已选值过滤需求实现问题

需求说明

多个DropDownList通过同一存储过程填充相同数据,当某一下拉框选中非默认值时,后续所有下拉框中需要移除该选项(例:ddl1选中“Value 1”,则ddl2、ddl3等不再显示该值)。

现有代码

前端DropDownList代码

<td>
    <asp:DropDownList ID="ddlEquipmentType1" runat="server" AppendDataBoundItems="true" AutoPostBack="true" Width="200px" />
    <asp:TextBox runat="server" name="txtIndoorUnit1SerialNumber" Placeholder="Serial #" MaxLength="20" ID="txtIndoorUnit1SerialNumber" Style="width: 200px;" errorName="<%$ Resources:Locale, Global_IndoorUnit1SerialNumber%>" />
    <span runat="server" id="vldReqIndoorUnit1SerialNumber" style="color: Red;" Visible="False">*</span>
</td>
</tr>
<tr id="trIndoorUnit2SerialNumber" runat="server" visible="false">
    <td style="vertical-align:top">
        <asp:label runat="server" id="Label30" Text="<%$ Resources:Locale, Global_IndoorUnit2SerialNumber%>" />
    </td>
    <td>
        <asp:DropDownList ID="ddlEquipmentType2" runat="server" AppendDataBoundItems="true" AutoPostBack="true" Width="200px" />
        <asp:TextBox runat="server" name="txtIndoorUnit2SerialNumber" Placeholder="Serial #" MaxLength="20" ID="txtIndoorUnit2SerialNumber" Style="width: 200px;" errorName="<%$ Resources:Locale, Global_IndoorUnit2SerialNumber%>" />
        <span runat="server" id="vldReqIndoorUnit2SerialNumber" style="color: Red;" Visible="False">*</span>
    </td>
</tr>

(其余下拉框结构与上述一致)

下拉框填充后台代码

Protected Sub PopEquipmentDDLs()
    Dim dt As DataTable = New DataTable
    Dim strSQL As String = "SELECT RecID, EquipmentType FROM EquipmentTypes WHERE RecID IN (SELECT PrimaryEType FROM ETRelationship WHERE RecID = @RecID UNION ALL SELECT AccessoryEType1 FROM ETRelationship WHERE RecID = @RecID UNION ALL SELECT AccessoryEType2 FROM ETRelationship WHERE RecID = @RecID UNION ALL SELECT AccessoryEType3 FROM ETRelationship WHERE RecID = @RecID UNION ALL SELECT AccessoryEType4 FROM ETRelationship WHERE RecID = @RecID UNION ALL SELECT AccessoryEType5 FROM ETRelationship WHERE RecID = @RecID UNION ALL SELECT AccessoryEType6 FROM ETRelationship WHERE RecID = @RecID UNION ALL SELECT AccessoryEType7 FROM ETRelationship WHERE RecID = @RecID UNION ALL SELECT AccessoryEType8 FROM ETRelationship WHERE RecID = @RecID UNION ALL SELECT AccessoryEType9 FROM ETRelationship WHERE RecID = @RecID) AND EquipmentType <> @PEquipmentType"
    Dim ddlCollection As New List(Of DropDownList)() From {ddlEquipmentType1, ddlEquipmentType2, ddlEquipmentType3, ddlEquipmentType4, ddlEquipmentType5, ddlEquipmentType6, ddlEquipmentType7, ddlEquipmentType8, ddlEquipmentType9}
    Dim selectedValues As New Dictionary(Of Integer, String)()

    'For i As Integer = 0 To ddlCollection.Count - 1
    '    Dim ddl As DropDownList = ddlCollection(i)
    '    If ddl.SelectedIndex > 0 Then
    '        selectedValues.Add(i, ddl.SelectedItem.Value)
    '    End If
    'Next

    Using conn As New SqlConnection(ConfigurationManager.ConnectionStrings("WillisConnectionString").ToString)
        Using cmdSQL As New SqlCommand(strSQL, conn)
            cmdSQL.Parameters.Add("RecID", SqlDbType.Int).Value = ddlNbZones.SelectedValue
            cmdSQL.Parameters.Add("PEquipmentType", SqlDbType.VarChar).Value = txtEType.Text
            conn.Open()
            dt.Load(cmdSQL.ExecuteReader())

            'Clear all drop-down lists
            For Each ddl As DropDownList In ddlCollection
                ddl.Items.Clear()
                ddl.Items.Add(New ListItem("---SELECT EQUIPMENT---", "0"))
            Next

            'populate drop-downs
            For i As Integer = 0 To ddlCollection.Count - 1
                Dim ddl As DropDownList = ddlCollection(i)

                ddl.DataSource = dt
                ddl.DataTextField = "EquipmentType"
                ddl.DataValueField = "RecID"
                ddl.DataBind()

                'If selectedValues.ContainsKey(i) Then
                '    ddl.SelectedValue = selectedValues(i)
                'End If
            Next

            For Each item In ddlEquipmentType2.Items
                System.Diagnostics.Debug.WriteLine(item)
            Next
        End Using
    End Using
End Sub

过滤逻辑后台代码

Private Sub FilterDDLs(ByVal ddlCollection As List(Of DropDownList))
    For i As Integer = 0 To ddlCollection.Count - 2
        Dim ddl As DropDownList = ddlCollection(i)

        ' Skip filtering if selected index is 0
        If ddl.SelectedIndex > 0 Then
            Dim selectedItemText As String = ddl.SelectedItem.Text

            For j As Integer = i + 1 To ddlCollection.Count - 1
                Dim subsequentDDL As DropDownList = ddlCollection(j)

                Dim itemToRemove As ListItem = subsequentDDL.Items.FindByText(selectedItemText)
                If itemToRemove IsNot Nothing Then
                    subsequentDDL.Items.Remove(itemToRemove)
                End If
            Next
        End If
    Next
End Sub

当前问题

  • 在DropDownList的DataBinding和SelectedIndexChanged事件中调用FilterDDLs,均无法移除索引大于0的选项;
  • 移除If ddl.SelectedIndex > 0 Then判断后,仅能移除填充时添加的默认项(值为0的选项),无法移除其他选项;
  • 尝试在填充过程中先保存选中值再重新绑定,也未成功。

解决方案

1. 修正填充过程:先保存选中值,绑定后恢复再过滤

修改PopEquipmentDDLs方法,确保在清空下拉框前保存所有选中值,绑定完成后恢复选中状态,最后执行过滤逻辑:

Protected Sub PopEquipmentDDLs()
    Dim dt As DataTable = New DataTable
    Dim strSQL As String = "SELECT RecID, EquipmentType FROM EquipmentTypes WHERE RecID IN (SELECT PrimaryEType FROM ETRelationship WHERE RecID = @RecID UNION ALL SELECT AccessoryEType1 FROM ETRelationship WHERE RecID = @RecID UNION ALL SELECT AccessoryEType2 FROM ETRelationship WHERE RecID = @RecID UNION ALL SELECT AccessoryEType3 FROM ETRelationship WHERE RecID = @RecID UNION ALL SELECT AccessoryEType4 FROM ETRelationship WHERE RecID = @RecID UNION ALL SELECT AccessoryEType5 FROM ETRelationship WHERE RecID = @RecID UNION ALL SELECT AccessoryEType6 FROM ETRelationship WHERE RecID = @RecID UNION ALL SELECT AccessoryEType7 FROM ETRelationship WHERE RecID = @RecID UNION ALL SELECT AccessoryEType8 FROM ETRelationship WHERE RecID = @RecID UNION ALL SELECT AccessoryEType9 FROM ETRelationship WHERE RecID = @RecID) AND EquipmentType <> @PEquipmentType"
    Dim ddlCollection As New List(Of DropDownList)() From {ddlEquipmentType1, ddlEquipmentType2, ddlEquipmentType3, ddlEquipmentType4, ddlEquipmentType5, ddlEquipmentType6, ddlEquipmentType7, ddlEquipmentType8, ddlEquipmentType9}
    Dim selectedValues As New Dictionary(Of Integer, String)()

    ' 1. 清空下拉框前,保存所有已选中的非默认值
    For i As Integer = 0 To ddlCollection.Count - 1
        Dim ddl As DropDownList = ddlCollection(i)
        If ddl.SelectedIndex > 0 Then
            selectedValues.Add(i, ddl.SelectedItem.Value)
        End If
    Next

    Using conn As New SqlConnection(ConfigurationManager.ConnectionStrings("WillisConnectionString").ToString)
        Using cmdSQL As New SqlCommand(strSQL, conn)
            cmdSQL.Parameters.Add("RecID", SqlDbType.Int).Value = ddlNbZones.SelectedValue
            cmdSQL.Parameters.Add("PEquipmentType", SqlDbType.VarChar).Value = txtEType.Text
            conn.Open()
            dt.Load(cmdSQL.ExecuteReader())

            'Clear all drop-down lists
            For Each ddl As DropDownList In ddlCollection
                ddl.Items.Clear()
                ddl.Items.Add(New ListItem("---SELECT EQUIPMENT---", "0"))
            Next

            'populate drop-downs
            For i As Integer = 0 To ddlCollection.Count - 1
                Dim ddl As DropDownList = ddlCollection(i)

                ddl.DataSource = dt
                ddl.DataTextField = "EquipmentType"
                ddl.DataValueField = "RecID"
                ddl.DataBind()

                ' 2. 绑定完成后,恢复之前保存的选中值
                If selectedValues.ContainsKey(i) Then
                    Dim targetItem As ListItem = ddl.Items.FindByValue(selectedValues(i))
                    If targetItem IsNot Nothing Then
                        ddl.SelectedValue = selectedValues(i)
                    End If
                End If
            Next

            ' 3. 恢复选中状态后,执行过滤逻辑
            FilterDDLs(ddlCollection)

            For Each item In ddlEquipmentType2.Items
                System.Diagnostics.Debug.WriteLine(item)
            Next
        End Using
    End Using
End Sub

2. 优化过滤逻辑:用Value而非Text查找选项

由于RecID是主键唯一值,用FindByValue比FindByText更准确,避免文本重复导致的错误:

Private Sub FilterDDLs(ByVal ddlCollection As List(Of DropDownList))
    For i As Integer = 0 To ddlCollection.Count - 2
        Dim ddl As DropDownList = ddlCollection(i)

        ' Skip filtering if selected index is 0
        If ddl.SelectedIndex > 0 Then
            Dim selectedValue As String = ddl.SelectedItem.Value

            For j As Integer = i + 1 To ddlCollection.Count - 1
                Dim subsequentDDL As DropDownList = ddlCollection(j)

                Dim itemToRemove As ListItem = subsequentDDL.Items.FindByValue(selectedValue)
                If itemToRemove IsNot Nothing Then
                    subsequentDDL.Items.Remove(itemToRemove)
                End If
            Next
        End If
    Next
End Sub

3. 绑定统一的选中变更事件

给所有DropDownList绑定同一个SelectedIndexChanged事件处理方法,确保选中变化时触发重新填充和过滤:

Protected Sub ddlEquipmentType_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ddlEquipmentType1.SelectedIndexChanged, ddlEquipmentType2.SelectedIndexChanged, ddlEquipmentType3.SelectedIndexChanged, ddlEquipmentType4.SelectedIndexChanged, ddlEquipmentType5.SelectedIndexChanged, ddlEquipmentType6.SelectedIndexChanged, ddlEquipmentType7.SelectedIndexChanged, ddlEquipmentType8.SelectedIndexChanged, ddlEquipmentType9.SelectedIndexChanged
    PopEquipmentDDLs()
End Sub

内容的提问来源于stack exchange,提问作者WhiteGlint

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 08:52:02