【问题标题】:Dropdown's SelectedIndexChanged event is not fired when its populated from client side从客户端填充下拉菜单的 SelectedIndexChanged 事件时不会触发
【发布时间】:2015-02-05 12:12:29
【问题描述】:

我的页面上有一个下拉列表,我从客户端 JavaScript 代码填充。 SelectedIndexChanged 不会触发。但是当我从代码隐藏(.cs 文件)中填充我的下拉列表时,甚至会被触发。

知道如何处理SelectedIndexChanged 从后面的代码填充下拉菜单。我可以看到根据我的需要填充下拉列表。只有SelectedIndexChanged 甚至没有被解雇。另请注意,下拉列表位于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 弹出窗口,它有一个多选下拉列表。由于弹出窗口中的按钮不能有服务器端事件,我使用 ajax 调用 .cs 文件中的 web 方法。此方法将使用在多选下拉列表中选择的选项从数据库中更新我的表。完成后,我想关闭弹出窗口并根据在多选中选择的选项填充下拉列表。

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

【问题讨论】:

  • 这个#ddS 有没有属性:runat="server"
  • @demo 是的,它有 runat 属性。检查我上面的 HTML。

标签: javascript c# jquery asp.net selectedindexchanged


【解决方案1】:

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

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

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

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

2) 忘记服务器端代码,使用 JavaScript 创建和填充&lt;select&gt; 控件。

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

b) 如果您需要将这些更改与服务器端代码进行通信,您可以绑定 JavaScript 事件侦听器以在选择更改时运行 POST 或 GET(AJAX 请求)。你从来没有真正说过你的目标是什么......

问题更新后编辑:

我能想到三种方法:

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

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

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

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

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

2) 将选中的项目写入隐藏字段,并在 POST 时从隐藏字段中收集值。

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

[WebMethod(EnableSession = true)]

【讨论】:

  • 感谢您的宝贵回答。我会努力实现你所说的。请参阅我的问题的已编辑部分以了解有关我的问题的更多详细信息。
  • 您是在使用 POST/GET 来刷新表格数据(页面刷新)还是在使用 AJAX 或 UpdatePanel?
  • 我用过 POST 方法
【解决方案2】:

通常,您需要确保在所有 DOM 操作之后设置您的事件处理程序(您的 SelectedIndexChanged)。在您的情况下,您通过 jQuery 的 append 方法附加您的 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);

【讨论】:

  • insie settimeout 函数我需要做什么?
  • 我可以像你在你的例子中给出的那样从 jquery 调用我的 cs 事件吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-08
  • 1970-01-01
相关资源
最近更新 更多