为什么在Javascript中附加一个事件处理程序会阻止我的服务器端事件触发?

时间:2009-03-01 00:16:27

标签: c# asp.net javascript

我已经做了多年的C#但是ASP.NET不用多久了,这让我很难过。

在我的故障排除示例中,我在ASP.NET页面中有一个下拉列表,其中有四个项目,我有一个在selectedindexchanged上触发的服务器端事件,在这种情况下它都很有效。

但是,如果(正如我在我的演进代码中)我为“onchange”事件设置了一个Javascript处理程序(启动警报),警报工作正常,但服务器端事件不再触发......我我确定我错过了一些明显的东西。

重要说明:在{dropdownlist >>控件上设置为Autopostback,启用了viewstate,Javascript事件处理程序返回true

任何?

这不是我必须手动连接__doPostBack是吗?

非常感谢任何帮助。

修改

这里的代码首先是代码隐藏

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Text;

namespace TestEvents
{
public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    protected override void OnPreRender(EventArgs e)
    {

        ClientScriptManager csm = Page.ClientScript;
        if (!csm.IsClientScriptBlockRegistered("NotesChangeScript"))
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("\r\n <script type=\"text/javascript\"> \r\n");
            sb.Append(" //<![CDATA[ \r\n");
            sb.Append(" var changesCount = 0; \r\n");

            sb.Append(" function selection_handler()\r\n");
            sb.Append("{ \r\n");
            sb.Append(" changesCount += 1;\r\n");
            sb.Append(" alert('i changed on the client!'); \r\n");
            sb.Append(" return true; \r\n");
            sb.Append(" } \r\n");

            sb.Append(" function SetUpNotesHandler() \r\n");
            sb.Append("{ \r\n");
            sb.Append("          var ctrls = document.getElementsByTagName(\"SELECT\");\r\n");
            sb.Append("          for(i=0;i<ctrls.length;i++)\r\n");
            sb.Append("                  {\r\n");
            sb.Append("                     ctrls[i].onchange = selection_handler; \r\n");
            sb.Append("                 }\r\n");
            sb.Append("}\r\n");


            sb.Append(" //]]> \r\n");
            sb.Append("</script>");

            csm.RegisterClientScriptBlock(this.GetType(), "NotesChangeScript", sb.ToString(), false);

            StringBuilder initScript = new StringBuilder();
            initScript.Append("<script type=\"text/javascript\" >\r\n");
            initScript.Append(" //<![CDATA[\r\n");
            initScript.Append("  SetUpNotesHandler(); \r\n");
            initScript.Append(" //]]> \r\n");
            initScript.Append("</script> \r\n");
            csm.RegisterStartupScript(this.GetType(), "StartUpKey", initScript.ToString(),false);
            base.OnPreRender(e);
        }

    }
    protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
    {
        Response.Write("i hit the server event");
    }
}

}

这是页面的标记

<%@ Page Language="C#" AutoEventWireup="true"     CodeBehind="Default.aspx.cs"    Inherits="TestEvents._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>problem</title>
</head>
<body>
<form id="form1" runat="server">
<div>
    <asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="True" OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged">
        <asp:ListItem>Numero Uno</asp:ListItem>
        <asp:ListItem>Numer Deux</asp:ListItem>
        <asp:ListItem>Number Three</asp:ListItem>
        <asp:ListItem>Nomina Quatros</asp:ListItem>
    </asp:DropDownList>
    <asp:HiddenField ID="hdnFieldChange" runat="server" />
</div>
</form>
</body>
</html>

4 个答案:

答案 0 :(得分:0)

听起来像你有两个同时发生的异步回发同时发生,默认情况下,最新的回发优先,你必须改变。您可以强制回发到每个完成,然后允许下一个回复继续发现脚本here

或者您可以在onselectedindex更改的事件中处理警报服务器端,例如:

    ScriptManager.RegisterClientScriptBlock(Page, Page.GetType(), 
Guid.NewGuid().ToString(),"alert('Person was added 
successfully.');location.replace('people.aspx');",true);

答案 1 :(得分:0)

如果您的Javascript事件处理程序取消了事件冒泡,那么由asp.net插入的调用服务器端代码的事件处理程序将无法运行。

我不熟悉asp.net自动插入的东西,你还没有发布你的事件处理程序的代码,所以我不能告诉你如何解决问题。我的建议是使用jQuery来附加你的事件处理程序,而不是返回false或以更详细的方式取消事件冒泡。

答案 2 :(得分:0)

将脚本分配给onchange事件:

DropDownList1.Attributes["onchange"] += "alert('alert');";

警告后不要使用 return true;

编辑:

问题出在这里,您通过在其上分配脚本来禁用回发脚本,因此回发脚本不起作用,因为它不再存在:

sb.Append("                     ctrls[i].onchange += selection_handler; \r\n");

希望这有帮助!

答案 3 :(得分:0)

好的,首先,感谢ScarletGarden明确了问题是什么,我已经假设了很多,但当有人确认你的怀疑时它很好。

其次,向那些认为这是某种n00b问题的人道歉,并发现这个问题的全部前提是愚蠢的,我真的找不到任何澄清这个具体问题的文章......

第三,我现在已经解决了如何在Javascript中做到这一点(尽管猩红色花园解决方案在几乎所有情况下都简单得多)尽管如果你有多个处理程序,属性.add方法(如scarletGarden所建议的)可能会受到影响需要他们以某种顺序发射。

在反射器中进行了一些挖掘后,Attributes.Add通过半冒号分隔它们来添加事件引用,因此这显然有效,因为它保留了已声明的任何处理程序,并且用分号分隔了您添加的处理程序。 / p>

在javascript中,这种链接(多种类型)需要使用DOM级别2功能(javascript圣经对于识别这一点很有用),Mozilla和IE有不同的方法实现同样的事情,为了添加一个js处理程序并保留代码隐藏中的事件处理,我上面的例子中的行说

ctrls[i].onchange = selection_handler; \r\n

需要被以下内容取代(在人们对这个例子感到高兴之前,我对此有一个很大的警告,进一步向下)

sb.Append("                 if (ctrls[i].addEventListener) ctrls[i].addEventListener(\"change\",selection_handler,false);");
sb.Append("                 else if (ctrls[i].attachEvent) ctrls[i].attachEvent(\"on\" + \"change\", selection_handler, false);");
sb.Append("                 else return false;");

attachEvent在IE中运行,在Firefox中使用addEventListener(注意事件的不同名称,Mozilla更愿意放弃“on”

添加这样的事件以LIFO(后进先出)的方式工作,有很多替代方法可以使用更精细的javascript以这种方式对事件进行排序,这是一个很好的,如果有点混乱的线程(因为它的启动方式) )http://codingforums.com/showthread.php?t=154673

我希望这些东西能像我一样启发他人,这是我第一次遇到这个问题时所寻找的主题,现在我觉得有点傻,但是嘿嘿