如何在ASP.NET中实现多选ListBox关闭下拉时自动回发触发SelectedIndexChanged事件
问题根因
你手动调用__doPostBack时传入的第一个参数是ListBox渲染后的客户端ID(下划线分隔),但ASP.NET识别控件事件需要的是控件的UniqueID(美元符号分隔,母版页/嵌套容器场景下和客户端ID不一致),导致框架无法匹配到对应的ListBox控件,自然不会触发SelectedIndexChanged事件。
解决方案
有两种可落地的实现方式,选其中一种即可:
方案1:修正回发参数直接触发SelectedIndexChanged事件
- 先修改ListBox控件定义,把UniqueID存入自定义属性,方便JS获取:
<asp:ListBox ID="NameListBox" runat="server" CssClass="multiselect" SelectionMode="Multiple" OnSelectedIndexChanged="NameListBox_SelectedIndexChanged" data-unique-id="<%= NameListBox.UniqueID %>"> <asp:ListItem Text="Name 1" /> <asp:ListItem Text="Name 2" /> <asp:ListItem Text="Name 3" /> <asp:ListItem Text="Name 4" /> <asp:ListItem Text="Name 5" /> <asp:ListItem Text="Name 6" /> </asp:ListBox>
- 修改Bootstrap Multiselect的初始化JS,用
UniqueID作为回发的事件目标参数:
$('.multiselect').multiselect({ nonSelectedText: '', nSelectedText: 'selected', allSelectedText: 'Everyone', numberDisplayed: 2, buttonTextAlignment: 'left', buttonWidth: 240, onDropdownHidden: function (event) { // 直接从当前select元素的自定义属性取UniqueID __doPostBack($(this).data('unique-id'), ''); } });
- 保持ListBox的
AutoPostBack为默认的false即可,不要手动设为true。
方案2:直接在Page_Load中匹配回发来源执行逻辑(更稳妥,无事件触发依赖)
如果你不想纠结控件事件的触发条件,可以直接跳过事件机制,在页面生命周期里判断回发来源执行逻辑:
- JS初始化代码可沿用方案1的写法,确保回发参数正确即可。
- 在后台的
Page_Load方法里加判断逻辑:
protected void Page_Load(object sender, EventArgs e) { if (IsPostBack) { string eventTarget = Request.Form["__EVENTTARGET"]; // 匹配到是ListBox下拉关闭触发的回发 if (eventTarget == NameListBox.UniqueID) { // 直接调用你原来写在SelectedIndexChanged里的处理逻辑即可 // 建议把原来的处理代码封装成独立方法,比如SaveSelectedItems(),在这里调用 SaveSelectedItems(); } } }
验证注意事项
回发后可以先调试查看NameListBox.GetSelectedIndices()或者NameListBox.Items.Cast<ListItem>().Where(i=>i.Selected)的结果,确认选中状态已经被Bootstrap Multiselect正确同步到原生控件,只要状态同步正常,上面两种方案都能正常执行你的保存逻辑。
内容的提问来源于stack exchange,提问作者Dinosbacsi
相关产品推荐
相关产品推荐

