无法在嵌入UpdatePanel的WebControl中获取ScriptManager.RegisterStartupScript

时间:2009-04-29 14:04:36

标签: c# asp.net ajax updatepanel scriptmanager

我有我认为应该是一个相当简单的问题,但对于我的生活,我看不出我的问题。问题与ScriptManager.RegisterStartupScript有关,这是我之前多次使用过的。

我的方案是我有一个已插入页面的自定义Web控件。控件(以及一个或两个其他)嵌套在UpdatePanel中。它们被插入到PlaceHolder上:

<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);

我也尝试过:

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

问题是脚本在首次显示页面时正确运行,但在部分回发后不会重新运行。我尝试过以下方法:

  1. 从CreateChildControls调用RegisterStartupScript
  2. 从OnLoad / OnPreRender调用RegisterStartupScript
  3. 为前两个参数使用不同的参数组合(在上面的示例中,Control是Page和Type是GetType(),但我尝试过使用控件本身等)。
  4. 我尝试过使用持久性和新的ID(不是我认为这应该会产生重大影响)。
  5. 我使用了一些断点,因此确认正确调用了注册行。
  6. 我唯一没有尝试的是使用UpdatePanel本身作为Control和Type,因为我不相信控件应该知道更新面板(并且无论如何似乎没有一个好方法获取更新面板?)。

    任何人都可以看到上面我可能做错了吗?

    谢谢:)


    好吧,回答上面的查询 - 它看起来好像占位符以某种方式混淆了ScriptManager.RegisterStartupScript。

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

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

    有人可以解释为什么注入控件到PlaceHolder会阻止ScriptManager正确注册脚本吗?我猜这可能与动态控件的生命周期有关,但如果上面有正确的过程,我会很感激(据我所知)。

10 个答案:

答案 0 :(得分:34)

我在用户控件中使用它时出现了问题(在这个页面中工作正常); Button1位于updatepanel内,scriptmanager位于usercontrol

protected void Button1_Click(object sender, EventArgs e)  
{  
    string scriptstring = "alert('Welcome');";  
    ScriptManager.RegisterStartupScript(this, this.GetType(), "alertscript", scriptstring, true);  
}

现在看来你必须要小心前两个参数,他们需要引用你的页面而不是你的控件

ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "alertscript", scriptstring, true);

答案 1 :(得分:15)

我认为你应该使用RegisterStartupScript的Control overload

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

[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事件都会触发 - 这样您就可以调用方法来设置控件。

我唯一的其他问题是:

  • 你的剧本实际上在做什么?
  • 据推测,您可以在页面底部的HTML中看到该脚本(在结束&lt; / form&gt;标记之前)?
  • 您是否尝试过“警告”(“此处”);“在启动脚本中调用以查看它是否被正确调用?
  • 您是否尝试过Firefox和Firebug - 报告任何脚本错误?

答案 2 :(得分:10)

调用ScriptManager.RegisterStartupScript时,“Control”参数必须是将更新的UpdatePanel中的控件。您需要将其更改为:

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

答案 3 :(得分:1)

解决方案是将脚本放在外部js文件中(我们称之为'yourDynamic.js')并在每次刷新updatepanel时重新注册de file。

我在updatepanel_prerender事件中使用它:

ScriptManager.RegisterClientScriptBlock(UpdatePanel1, UpdatePanel1.GetType(), "UpdatePanel1_PreRender", _
                   "<script type='text/javascript' id='UpdatePanel1_PreRender'>" & _
                   "include('yourDynamic.js');" & _
                   "removeDuplicatedScript('UpdatePanel1_PreRender');</script>" _
                   , False)

在页面或其他一些内容中,您需要使用此javascript:

// Include a javascript file inside another one.
function include(filename)
{
    var head = document.getElementsByTagName('head')[0];

    var scripts = document.getElementsByTagName('script');
    for(var x=0;x<scripts.length;>    {
        if (scripts[x].getAttribute('src'))
        {
            if(scripts[x].getAttribute('src').indexOf(filename) != -1)
            {
                head.removeChild(scripts[x]);
                break;
            }
        }
    }

    script = document.createElement('script');
    script.src = filename;
    script.type = 'text/javascript';
    head.appendChild(script)
}

// Removes duplicated scripts.
function removeDuplicatedScript(id)
{
    var count = 0;
    var head = document.getElementsByTagName('head')[0];

    var scripts = document.getElementsByTagName('script');
    var firstScript;
    for(var x=0;x<scripts.length;>    {
        if (scripts[x].getAttribute('id'))
        {
            if(scripts[x].getAttribute('id').indexOf(id) != -1)
            {
                if (count == 0)
                {
                    firstScript = scripts[x];
                    count++;
                }
                else
                {
                    head.removeChild(firstScript);
                    firstScript = scripts[x];
                    count = 1;
                }
            }
        }
    }
    clearAjaxNetJunk();
}
// Evoids the update panel auto generated scripts to grow to inifity. X-(
function clearAjaxNetJunk()
{
    var knowJunk = 'Sys.Application.add_init(function() {';
    var count = 0;
    var head = document.getElementsByTagName('head')[0];

    var scripts = document.getElementsByTagName('script');
    var firstScript;
    for(var x=0;x<scripts.length;>    {
        if (scripts[x].textContent)
        {
            if(scripts[x].textContent.indexOf(knowJunk) != -1)
            {
                if (count == 0)
                {
                    firstScript = scripts[x];
                    count++;
                }
                else
                {
                    head.removeChild(firstScript);
                    firstScript = scripts[x];
                    count = 1;
                }
            }
        }
    }
}

非常酷,啊...... jejeje 这段时间我发布的here

希望这有帮助...:)

答案 4 :(得分:1)

我遇到了Page.ClientScript.RegisterStartUpScript的问题 - 我没有使用更新面板,但控件已缓存。这意味着我必须将脚本插入Literal(或者可以使用PlaceHolder),因此当从缓存中呈现时,脚本就会被包含在内。

类似的解决方案可能适合您。

答案 5 :(得分:1)

请勿使用GUID for Key

ScriptManager.RegisterClientScriptBlock(this.Page, typeof(UpdatePanel) 
       Guid.NewGuid().ToString(), myScript, true);

如果你想这样做,请调用Something Like this function

 public static string GetGuidClear(string x)
 {
      return x.Replace("-", "").Replace("0", "").Replace("1", "")
              .Replace("2",  "").Replace("3", "").Replace("4", "")
              .Replace("5", "").Replace("6", "").Replace("7", "")
              .Replace("8", "").Replace("9", "");
 }

答案 6 :(得分:0)

我尝试了很多东西,最后发现最后一个参数必须为false,你必须将<SCRIPT>标记添加到java脚本中:

string script = "< SCRIPT >alert('hello!');< /SCRIPT>";

ScriptManager.RegisterClientScriptBlock(Page, Page.GetType(), key, script, **false**);

答案 7 :(得分:0)

对我有用的是,在将页面指定为UpdatePanel的类型时将其注册到页面上,如下所示:

ScriptManager.RegisterClientScriptBlock(this.Page, typeof(UpdatePanel) Guid.NewGuid().ToString(), myScript, true);

答案 8 :(得分:0)

当脚本出现语法错误时,有时它不会触发,请确保脚本和javascript语法正确。

答案 9 :(得分:0)

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

ScriptManager.RegisterStartupScript末尾的“true”参数值将在页面中添加JavaScript标记:

<script language='javascript' defer='defer'>your script</script >

如果该值为“false”,则只会注入带有--script--标记的脚本。