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
相关产品推荐
相关产品推荐

