C# 无法使嵌套在 UpdatePanel 中的 WebControl 中的 ScriptManager.RegisterStartupScript 工作

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/802506/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 01:47:33  来源:igfitidea点击:

Can't get ScriptManager.RegisterStartupScript in WebControl nested in UpdatePanel to work

c#asp.netajaxupdatepanelscriptmanager

提问by Chris

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.

我遇到了我认为应该是一个相当简单的问题,但对于我的生活,我看不到我的问题。问题与ScriptManager.RegisterStartupScript有关,我以前用过很多次。

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:

我的情况是我有一个已插入页面的自定义 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);
}

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:

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

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.
  1. 从 CreateChildControls 调用 RegisterStartupScript
  2. 从 OnLoad / OnPreRender 调用 RegisterStartupScript
  3. 对前两个参数使用不同的参数组合(在上面的示例中,Control 是 Page,Type 是 GetType(),但我尝试过使用控件本身等)。
  4. 我曾尝试使用持久的和新的 id(并不是说我认为这应该以任何方式产生重大影响)。
  5. 我使用了一些断点,因此已验证是否正确调用了 Register 行。

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?).

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

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.

好吧,回答上面的问题 - 它看起来好像占位符以某种方式弄乱了 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).

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

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.

任何人都可以解释为什么注入的控件到 PlaceHolder 会阻止 ScriptManager 正确注册脚本?我猜这可能与动态控件的生命周期有关,但如果有上述正确的过程,我会很感激(就我自己的知识而言)。

采纳答案by Zhaph - Ben Duguid

I think you should indeed be using the Control overloadof the RegisterStartupScript.

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

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.

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

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 endRequestHandlerevent fires every time an update panel completes its update - this would allow you to call a method to set up your control.

PageRequestManager endRequestHandler事件触发每一个更新面板完成其更新时间-这将让你调用一个方法来建立你的控制。

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?
  • 你的脚本实际上在做什么?
  • 大概您可以在页面底部的 HTML 中看到脚本(就在结束 </form> 标记之前)?
  • 你有没有试过放一些“警报(“这里”);“ 在您的启动脚本中调用以查看它是否被正确调用?
  • 您是否尝试过 Firefox 和Firebug- 是否报告任何脚本错误?

回答by Keltex

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 时,“Control”参数必须是将更新的 UpdatePanel 内的控件。您需要将其更改为:

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

回答by Lucas

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.

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

I use this in the updatepanel_prerender event:

我在 updatepanel_prerender 事件中使用它:

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:

在页面或其他一些包含中,您将需要此 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.

很酷,啊...jejeje 这是我前段时间在这里发布的内容的一部分。

Hope this help... :)

希望这有助于... :)

回答by s_hewitt

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.

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

A similar solution might work for you.

类似的解决方案可能对您有用。

回答by Zhaph - Ben Duguid

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

我尝试了很多东西,最后发现最后一个参数必须是假的,你必须<SCRIPT>在java脚本中添加标签:

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

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

回答by dc2009

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

我在用户控件中使用它时遇到了问题(在一个页面中工作正常);Button1 位于 内updatepanel,而scriptmanager位于 上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);

回答by Alex

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

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

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

回答by Prema Tiwari

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

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

回答by ahmad sarkar

DO NOT Use GUID For Key

不要使用 GUID 作为密钥

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

回答by ZoharAdar

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:

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

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

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

如果该值为“false”,它将仅注入没有 --script-- 标签的脚本。