当从客户端填充时,下拉列表的 SelectedIndexChanged 事件不会被触发

Dropdown's SelectedIndexChanged event is not fired when its populated from client side

我的页面上有一个下拉菜单,我是从客户端 javascript 代码填充的。 SelectedIndexChanged 不会触发。但是当我从代码隐藏(.cs 文件)填充我的下拉菜单时,even 被解雇了。

知道如何处理 SelectedIndexChanged 当从代码隐藏填充下拉列表时。我可以看到下拉列表正在根据我的需要进行填充。只有 SelectedIndexChanged even 没有被解雇。另请注意,下拉菜单位于 UpdatePanel 内。这会是一个原因吗?

这是我的 html、javascript 和事件背后的代码:

<asp:DropDownList ID="ddS" runat="server" OnSelectedIndexChanged="ddS_SelectedIndexChanged"
                AutoPostBack="True" Style="position: absolute; width: 50%;">

Javascript:

$('#ddS').append('<option value="' + $(this).val() + '">' + $(this).text() + '</option>');

CS

protected void ddS_SelectedIndexChanged(object sender, EventArgs e)
{
}

如有任何帮助,我们将不胜感激。提前致谢。

编辑 我这样做的主要原因是: 我使用 jquery ui js 作为弹出窗口,它有一个多 select 下拉列表。由于弹出窗口中的按钮不能有服务器端事件,我使用 ajax 调用 .cs 文件中的网络方法。此方法将使用 multi-select 下拉列表中的选项 selected 从数据库更新我的表。完成后,我想关闭弹出窗口并根据 multi-select.

中的 selected 选项填充下拉菜单

我无法从隐藏代码填充我的下拉列表,因为网络方法是静态方法,因此从该方法调用的任何方法都必须是静态方法。如果我编写静态方法,那么我无法从静态方法访问 UI 控件(我的下拉列表)。所以我希望我可以从 JS 填充它,然后触发我的 indexchange 事件以进行进一步计算。

通常,您需要确保您的事件处理程序(您的 SelectedIndexChanged)已设置 在所有 DOM 操作之后。在您的情况下,您通过 jQuery 的附加方法附加 html 元素。不幸的是,无法向该方法添加回调。 然而,带有计时器“1ms”的 settimeout 总是将函数放在调用堆栈底部的 settimeout 中。

$('#ddS').append('<option value="' + $(this).val() + '">' + $(this).text() + '</option>');
setTimeout(function() {
  // set listener here
  // e.g. $("#ddS option").change(function(){ 
  //   ddS_SelectedIndexChanged()
  // });
}, 1);

简短的回答是不要这样做。这不是 ASP.NET 服务器控件设计的工作方式,您最终将创建一个 Rube Goldburg 使其工作。详情如下:

ASP.NET 具有内置的安全功能(事件验证),以防止在页面生命周期的呈现阶段后发布控件中不存在的数据。如果发生这种情况,将抛出 ArgumentException。您可以禁用事件验证或覆盖 Render 并在 Page_Load 函数中添加大量代码,但我不推荐这样做。

那么为什么会发生这一切呢? ASP.NET 服务器控件使用 ViewState 来尝试创建类似于桌面应用程序中的状态(Windows Forms => Web Forms 看看他们在那里做了什么)。如果 ViewState 不知道您添加到 <select><options>,它会感到不安。一些解决方案是:

1) 在服务器端填充 DropDownList(除非您有充分的理由不这样做)并让 ASP.NET 框架执行其预期的操作(您 可以 还必须将 EnableViewState=true 属性添加到 DropDownList 控件,尽管我认为这是默认设置)。如果 DropDownList 在更新面板中,ViewState 会从面板触发的 PartialPostBack 更新,因此 ViewState 在您获得无闪烁更新时保持快乐。

2) 忘记服务器端代码并​​使用 JavaScript 创建和填充 <select> 控件。

a) 您可以绑定一个 JavaScript 事件侦听器以在 selected 项更改时更新隐藏字段。然后在 PostBack 上,您可以读取隐藏字段的值以获取最后一个 selected 项目的值。

b) 当 selection 发生变化时,您可以将 JavaScript 事件侦听器绑定到 运行 a POST 或 GET(AJAX 请求)您需要将这些更改与服务器端代码进行通信。你从来没有真正说过你的 objective 是什么...

问题更新后编辑:

我想到了三种方式:

1) 删除ASP DropDownList 控件并使其成为常规HTML select 控件。为控件命名(使用 name 属性而不仅仅是 id 属性)。例如:

<select name='options'></select>

在 POST 上,HttpContext.Current.Request.Form 是一个 NameValueCollection,它将包含 POSTed 数据的键值对。您应该能够使用您为 select 控件提供的名称从 select 控件中获取 selected 项目:

var options = HttpContent.Current.Request.Form["options"].Split(',');

options 现在将是 selected 值的列表。如果您需要启用 AJAX(无页面刷新),请将其包装在 UpdatePanel.

2) 将 selected 项写入隐藏字段并从 POST 上的隐藏字段收集值。

3) 将 POST 触发到更新会话对象的 Web 方法,然后可以从 class members/methods 后面的非静态代码中读取该对象。启用会话的 Web 方法装饰有一个可选属性:

[WebMethod(EnableSession = true)]