33

我遇到了我认为应该是一个相当简单的问题,但是对于我的生活,我看不到我的问题。问题与 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. 我使用了一些断点,因此验证了 Register 行被正确调用。

我唯一没有尝试过的是将 UpdatePanel 本身用作控件和类型,因为我不认为控件应该知道更新面板(无论如何似乎都不是获取更新的好方法控制板?)。

谁能看到我在上面做错了什么?

谢谢 :)


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

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

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

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

4

10 回答 10

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);
于 2009-11-09T16:27:35.260 回答
15

我认为您确实应该使用 RegisterStartupScript 的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);
    }
}

然后在我的页面中,我有:

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

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

这与您预期的完全一样,每次我加载页面或导致更新面板更新时,我都会收到一条警告说“你好”。

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

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

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

我唯一的其他问题是:

  • 你的脚本实际上在做什么?
  • 大概您可以在页面底部的 HTML 中看到脚本(就在结束 </form> 标记之前)?
  • 你试过放几个“alert(“Here”);” 在您的启动脚本中调用以查看它是否被正确调用?
  • 您是否尝试过 Firefox 和Firebug - 是否报告任何脚本错误?
于 2009-04-29T22:03:07.423 回答
10

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

ScriptManager.RegisterStartupScript(this, this.GetType(), Guid.NewGuid().ToString(), script, true);
于 2009-04-29T14:35:57.357 回答
1

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

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

希望这有帮助... :)

于 2009-04-29T20:42:48.300 回答
1

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

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

于 2009-04-29T20:55:11.097 回答
1

不要将 GUID 用于密钥

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", "");
 }
于 2011-07-25T05:11:23.690 回答
0

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

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

ScriptManager.RegisterClientScriptBlock(Page, Page.GetType(), key, script, **false**);
于 2009-05-27T19:07:54.667 回答
0

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

ScriptManager.RegisterClientScriptBlock(this.Page, typeof(UpdatePanel) Guid.NewGuid().ToString(), myScript, true);
于 2009-12-22T11:46:33.090 回答
0

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

于 2011-01-20T07:45:41.547 回答
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-- 标签的脚本。

于 2012-02-02T15:59:44.467 回答