无法让 UpdatePanel 中嵌套的 WebControl 中的 ScriptManager.RegisterStartupScript 工作

发布于 2024-07-18 22:18:12 字数 1775 浏览 3 评论 0原文

我遇到了我认为应该是一个相当简单的问题,但我一生都看不到我的问题。 该问题与 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);

并且我也尝试过:

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

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

  1. 从 CreateChildControls 调用 RegisterStartupScript
  2. 从 OnLoad / OnPreRender 调用 RegisterStartupScript
  3. 对前两个参数使用不同的参数组合(在上面的示例中,Control 是 Page,Type 是 GetType(),但我尝试使用控件本身, ETC)。
  4. 我尝试过使用持久的和新的 id(并不是说我相信这应该会产生重大影响)。
  5. 我使用了一些断点,因此验证了 Register 行是否被正确调用。

我唯一没有尝试过的是使用 UpdatePanel 本身作为控件和类型,因为我不认为控件应该知道更新面板(并且在任何情况下似乎都没有一种获取更新的好方法)控制板?)。

有人能看出我在上面做错了什么吗?

谢谢:)


好吧,回答上面的查询 - 看起来占位符确实以某种方式弄乱了 ScriptManager.RegisterStartupScript。

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

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

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

I am having what I believe should be a fairly simple problem, but for the life of me I cannot see my problem. The problem is related to ScriptManager.RegisterStartupScript, something I have used many times before.

The scenario I have is that I have a custom web control that has been inserted into a page. The control (and one or two others) are nested inside an UpdatePanel. They are inserted onto the page onto a 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);
}

This is the only update panel on the page.

The control requires some initial javascript be run for it to work correctly. The control calls:

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

and I have also tried:

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

The problem is that the script runs correctly when the page is first displayed, but does not re-run after a partial postback. I have tried the following:

  1. Calling RegisterStartupScript from CreateChildControls
  2. Calling RegisterStartupScript from OnLoad / OnPreRender
  3. Using different combinations of parameters for the first two parameters (in the example above the Control is Page and Type is GetType(), but I have tried using the control itself, etc).
  4. I have tried using persistent and new ids (not that I believe this should have a major impact either way).
  5. I have used a few breakpoints and so have verified that the Register line is being called correctly.

The only thing I have not tried is using the UpdatePanel itself as the Control and Type, as I do not believe the control should be aware of the update panel (and in any case there does not seem to be a good way of getting the update panel?).

Can anyone see what I might be doing wrong in the above?

Thanks :)


Well, to answer the query above - it does appear as if the placeholder somehow messes up the ScriptManager.RegisterStartupScript.

When I pull the control out of the placeholder and code it directly onto the page the Register script works correctly (I am also using the control itself as a parameter).


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

Can anyone throw any light on why an injected control onto a PlaceHolder would prevent the ScriptManager from correctly registering the script? I am guessing this might have something to do with the lifecycle of dynamic controls, but would appreciate (for my own knowledge) if there is a correct process for the above.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

遮云壑 2024-07-25 22:18:13

我在用户控件中使用它时遇到问题(在页面中工作正常); 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);

I had an issue using this in a user control (in a page this worked fine); the Button1 is inside an updatepanel, and the scriptmanager is on the usercontrol.

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

Now it seems you have to be careful with the first two arguments, they need to reference your page, not your control

ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "alertscript", scriptstring, true);
羁绊已千年 2024-07-25 22:18:13

我认为您确实应该使用 RegisterStartupScript 的控制重载

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

[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 中看到该脚本(就在结束 标记之前)?
  • 您是否尝试过添加一些“alert(”Here”);” 调用您的启动脚本以查看它是否被正确调用?
  • 您是否尝试过 Firefox 和 Firebug - 是否报告任何脚本错误?

I think you should indeed be using the Control overload of the RegisterStartupScript.

I've tried the following code in a server control:

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

Then in my page I have:

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

Where Placeholder1 is a placeholder in an update panel. The placeholder has a couple of other controls on in it, including buttons.

This behaved exactly as you would expect, I got an alert saying "Hello" every time I loaded the page or caused the update panel to update.

The other thing you could look at is to hook into some of the page lifecycle events that are fired during an update panel request:

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

The PageRequestManager endRequestHandler event fires every time an update panel completes its update - this would allow you to call a method to set up your control.

My only other questions are:

  • What is your script actually doing?
  • Presumably you can see the script in the HTML at the bottom of the page (just before the closing </form> tag)?
  • Have you tried putting a few "alert("Here");" calls in your startup script to see if it's being called correctly?
  • Have you tried Firefox and Firebug - is that reporting any script errors?
ˇ宁静的妩媚 2024-07-25 22:18:13

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

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

When you call ScriptManager.RegisterStartupScript, the "Control" parameter must be a control that is within an UpdatePanel that will be updated. You need to change it to:

ScriptManager.RegisterStartupScript(this, this.GetType(), Guid.NewGuid().ToString(), script, true);
忆悲凉 2024-07-25 22:18:13

解决方案是将脚本放入外部 js 文件(称为“yourDynamic.js”)中,并在每次刷新更新面板时重新注册该文件。

我在 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
这部分内容是我前段时间发布的 这里

希望这有帮助...:)

The solution is to put the scripts in an outside js file (lets called 'yourDynamic.js') and re-register de file everytime you refresh the updatepanel.

I use this in the updatepanel_prerender event:

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

In the page or in some other include you will need this 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;
                }
            }
        }
    }
}

Pretty cool, ah...jejeje
This part of what i posted some time ago here.

Hope this help... :)

暮凉 2024-07-25 22:18:13

我遇到了 Page.ClientScript.RegisterStartUpScript 问题 - 我没有使用更新面板,但控件已缓存。 这意味着我必须将脚本插入到文字中(或者可以使用占位符),以便从缓存渲染时包含脚本。

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

I had an issue with Page.ClientScript.RegisterStartUpScript - I wasn't using an update panel, but the control was cached. This meant that I had to insert the script into a Literal (or could use a PlaceHolder) so when rendered from the cache the script is included.

A similar solution might work for you.

英雄似剑 2024-07-25 22:18:13

不要使用 GUID 作为密钥

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

,如果你想这样做,请调用类似此函数的东西

 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", "");
 }

DO NOT Use GUID For Key

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

and if you want to do that , call 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", "");
 }
以歌曲疗慰 2024-07-25 22:18:13

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

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

What worked for me, is registering it on the Page while specifying the type as that of the UpdatePanel, like so:

ScriptManager.RegisterClientScriptBlock(this.Page, typeof(UpdatePanel) Guid.NewGuid().ToString(), myScript, true);
べ繥欢鉨o。 2024-07-25 22:18:13

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

Sometimes it doesnt fire when the script has some syntax error, make sure the script and javascript syntax is correct.

清醇 2024-07-25 22:18:13
ScriptManager.RegisterStartupScript(this, this.GetType(), Guid.NewGuid().ToString(),script,  true );

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

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

如果该值为“false”,它将仅注入不带 --script-- 标记的脚本。

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

The "true" param value at the end of the ScriptManager.RegisterStartupScript will add a JavaScript tag inside your page:

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

If the value will be "false" it will inject only the script witout the --script-- tag.

十年九夏 2024-07-25 22:18:13

我尝试了很多方法,最后发现最后一个参数必须为 false,并且必须将

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

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

I try many things and finally found that the last parameter must be false and you must add <SCRIPT> tag to the java script :

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

ScriptManager.RegisterClientScriptBlock(Page, Page.GetType(), key, script, **false**);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文