在客户端上重置原始值时,DropDownList SelectedIndexChanged不会运行

时间:2012-10-26 02:21:09

标签: c# jquery asp.net

这似乎是一个常见的场景,有一个明显的解决方案,但不知怎的,我没有遇到过它。

我有一个DropDownList,其中一个事件处理程序绑定到SelectedIndexChanged事件和AutoPostback="true",它按预期工作。

当值已更改时执行事件处理程序,但是如果在客户端使用jQuery通过脚本更改了值,则在用户更改值时会触发回发(以及下拉列表{ {1}}事件触发),然后服务器端代码检测到自服务器上次查看其状态后该值未发生更改,因此事件处理程序未在服务器端运行。

似乎会通过视图状态加载,但禁用onchange无效。

  1. 页面呈现下拉列表,选中值“A”。
  2. 用户将下拉列表更改为值“B”。
  3. 该值会自动发布到服务器,并执行ViewState事件处理程序。
  4. 运行客户端脚本,使用SelectedIndexChanged将客户端上的值更改回“A”。
  5. 用户将值更改回“B”。
  6. 该值会自动发布到服务器,但由于服务器上次呈现页面时值为“B”,因此不会执行jQuery.val()事件处理程序。
  7. 客户端

    SelectedIndexChanged

    服务器侧

    <asp:DropDownList ID="dlst" runat="server" AutoPostBack="true" OnSelectedIndexChanged="dlst_SelectedIndexChanged">
        <asp:ListItem Text="A" Value="A" />
        <asp:ListItem Text="B" Value="B" />
    </asp:DropDownList>
    
    <asp:Button ID="btnChange" runat="server" Text="Change" OnClientClick="return changeDDL(this,event)" />
    <script type="text/javascript">
        function changeDDL(sender, e) {
            var dlst = $("#<%= dlst.ClientID %>");
            dlst.val(dlst.val() === "A" ? "B" : "A");
            return false;
        }
    </script>
    

1 个答案:

答案 0 :(得分:2)

在调试.Net Framework Reference Source之后,我得出结论问题在DropDownList实现中很深,如果没有重新实现或继承类来改变行为,就无法解决问题。

DropDownList类中,LoadPostData()接口方法有IPostBackDataHandler个实现。

LoadPostData()内,将下拉列表中当前所选值的索引与从SelectedIndex加载或默认为ViewState的{​​{1}}属性进行比较在下拉列表中设置0时。

EnableViewState="false"方法调用OnSelectedIndexChanged()方法,正如名称所示,只有在发布数据与viewstate / default数据相比发生变化时才会调用RaisePostDataChangedEvent()方法。因此,如果当前选定的索引与viewstate / default索引匹配,则SelectedIndexChanged事件不会触发。

就我而言,有两件事可能导致问题:

  1. 启用ViewState后,当前索引值与SelectedIndex加载的ViewState值相匹配,因此SelectedIndexChanged不会触发。
  2. 禁用ViewState后,SelectedIndex值默认为0,因此当前索引值为0时,SelectedIndexChanged不会触发。
  3. <强> DropDownList.LoadPostData()

    protected virtual bool LoadPostData(String postDataKey, NameValueCollection postCollection) { 
        //{snip...}
        int n = Items.FindByValueInternal(selectedItems[0], false);
    
        if (SelectedIndex != n) {
            SetPostDataSelection(n); // Calls ListControl.SetPostDataSelection() and sets Items[selectedIndex].Selected = true;
            return true;
        } 
    
        return false; 
    }
    

    稍后,当Page类正在浏览其发布数据已更改的控件时,如果检测到更改,则会调用下拉列表的OnSelectedIndexChanged方法。由于下拉列表的后期数据在这种情况下没有改变,因此不会引发事件。

    <强> DropDownList.RaisePostDataChangedEvent()

    protected virtual void RaisePostDataChangedEvent() { 
        //{snip...}
        OnSelectedIndexChanged(EventArgs.Empty); 
    }