我有一个我认为应该是相当简单的问题,但就我的一生而言,我看不到我的问题.这个问题与ScriptManager有关.RegisterStartupScript,我以前使用过很多次.

我的场景是,我有一个自定义的web控件,该控件已插入到页面中.该控件(以及一个或两个其他控件)嵌套在UpdatePanel中.它们被插入到页面的占位符上:

<asp:UpdatePanel ID="pnlAjax" runat="server">
  <ContentTemplate>
    <asp:PlaceHolder ID="placeholder" runat="server">
    </asp:PlaceHolder>
    ...

protected override void OnInit(EventArgs e){
  placeholder.Controls.Add(Factory.CreateControl());
  base.OnInit(e);
}

这是页面上唯一的更新面板.

该控件需要运行一些初始javascript才能正常工作.控件调用:

ScriptManager.RegisterStartupScript(this, GetType(), 
                                    Guid.NewGuid().ToString(), script, true);

我也try 过:

ScriptManager.RegisterStartupScript(Page, Page.GetType(), 
                                    Guid.NewGuid().ToString(), script, true);

问题在于,第一次显示页面时脚本运行正常,但在部分回发后不会重新运行.我try 了以下方法:

  1. 从CreateChildControls调用RegisterStartupScript
  2. 从onLoad/OnPreRender调用RegisterStartupScript
  3. 对前两个参数使用不同的参数组合(在上面的示例中,Control是Page,Type是GetType(),但我try 使用控件本身,依此类推).
  4. 我已经try 使用永久ID和新ID(我并不认为这两种方式都会产生重大影响).
  5. 我使用了几个断点,因此验证了寄存器行是否被正确调用.

我唯一没有try 的是使用UpdatePanel本身作为Control和Type,因为我认为控件不应该知道更新面板(而且无论如何,似乎没有获得更新面板的好方法?).

有没有人看到我在上面可能做错了什么?

谢谢:)


好吧,为了回答上面的问题,占位符似乎确实搞乱了ScriptManager.RegisterStartupScript.

当我将控件从占位符中拉出并将其直接编码到页面上时,Register脚本可以正常工作(我还将控件本身用作参数).


ScriptManager.RegisterStartupScript(this, GetType(), Guid.NewGuid().ToString(), script, true);

有人能解释一下为什么在占位符上注入控件会阻止ScriptManager正确注册脚本吗?我猜这可能与动态控件的生命周期有关,但是(据我所知)如果有一个正确的过程来处理上述问题,我将不胜感激.

推荐答案

我认为您确实应该使用RegisterStartupScript的Control overload.

我在服务器控件中try 了以下代码:

[ToolboxData("<{0}:AlertControl runat=server></{0}:AlertControl>")]
public class AlertControl : Control{
    protected override void OnInit(EventArgs e){
        base.OnInit(e);
        string script = "alert(\"Hello!\");";
        ScriptManager.RegisterStartupScript(this, GetType(), 
                      "ServerControlScript", script, true);
    }
}

在我的页面中,我有:

protected override void OnInit(EventArgs e){
    base.OnInit(e);
    Placeholder1.Controls.Add(new AlertControl());
}

其中Placeholder1是更新面板中的占位符.占位符中还有几个其他控件,包括按钮.

这完全符合您的预期,每次我加载页面或导致更新面板更新时,都会收到一个警告,说"Hello".

您可以查看的另一件事是连接到更新面板请求期间触发的一些页面生命周期事件:

Sys.WebForms.PageRequestManager.getInstance()
   .add_endRequest(EndRequestHandler);

每次更新面板完成更新时都会触发PageRequestManager endRequestHandler事件,这将允许您调用一个方法来设置控件.

我唯一的其他问题是:

  • 你的 playbook 到底在做什么?
  • 您大概可以在页面底部的HTML中看到脚本(就在关闭<;/form>;标记之前)?
  • 你有没有试过放几句"警告("这里");"调用你的启动脚本,看看它是否被正确调用?
  • 你试过Firefox和Firebug了吗--有没有报告任何脚本错误?

Asp.net相关问答推荐

Razor中的共享本地化资源文件

如何在运行时判断动态数据类型的类型?

某些黑客能否从用户那里窃取 Web 浏览器 cookie 并在网站上使用该名称登录?

ASP.NET - AppDomain.CurrentDomain.GetAssemblies() - AppDomain 重新启动后缺少程序集

没有回发的按钮?

asp.net cookie、身份验证和会话超时

aspx 文件中的 if 语句

如何在 ASP.NET 下拉列表中添加选项组?

System.Web.MVC 自 MS14-059 以来未复制到 bin 文件夹中.如何防止由于 Windows 更新而创建缺少 DLL 的构建?

Eval()、XPath() 和 Bind() 等数据绑定方法只能在数据绑定控件的上下文中使用

ASP.NET 中的全局资源与本地资源

在asp.net控件之间动态添加

<%# Eval("State") %> 或 <%# DataBinder.Eval(Container.DataItem, "state")%>

您正在使用哪些身份验证和授权方案 - 为什么?

如何将表从存储过程检索到数据表?

.NET - c# - 需要跨分区查询,但在 DocumentDB 数据访问上禁用了问题

有没有办法在没有异常类的情况下抛出自定义异常

ExecuteReader:连接属性尚未初始化

DropDownList 的 SelectedValue 与 SelectedItem.Value

使用 FormsAuthentication.SetAuthCookie 存储更多信息