如何在部分回发上保留脚本块?

时间:2010-11-20 05:42:37

标签: javascript asp.net updatepanel scriptmanager

这是我正在处理的webapp中遇到的一个问题 因此,我没有使用不相关的代码来混淆问题,而是在一个孤立的,简化的webapp中重新创建了问题,只展示了这个问题。
希望这有助于找到解决方案。

我有一个网络用户控件,其内容为:

<% if (ShowAlertScript)
   { %>
       <script type="text/javascript">
           function AlertMe() 
           {
               alert('Hello World!');
           }
       </script>
<% } %>
<input type="button" onclick="AlertMe()" value="Say Hello" />

它的代码隐藏只不过是ShowAlertScript的布尔定义 这表示我在大型webapp中具有的控件有两种模式:输入模式显示模式。在输入模式时,它有一个大的javascript块,只有在那时才有用;它做了一些很酷的东西来帮助用户输入信息。

这种控制在大局中的布局如下:

<asp:ScriptManager runat="server" />
<asp:UpdatePanel runat="server">
  <ContentTemplate>
    <asp:MultiView ActiveViewIndex="0" runat="server" ID="mvw">
      <asp:View runat="server">
        <asp:Button runat="server" ID="btnSwitch" 
            OnClick="btnSwitch_Click" Text="Switch" />
      </asp:View>
      <asp:View runat="server">
        <uc:MyInputControl runat="server" ID="micInput" ShowAlertScript="true" />
      </asp:View>
    </asp:MultiView>
  </ContentTemplate>
</asp:UpdatePanel>

单击btnSwitch时,只需使用用户控件切换到第二个视图。 请注意我已将ShowAlertScript初始化为true的方式 可能的输出是,因为我在用户控件中“显示警报脚本”,所以{»1}}函数将在您单击AlertMe()元素时执行,因为它是根据内联{{ 1}}陈述。

如果你运行这段代码,我到目前为止,它将无法正常工作 浏览器会说它看不到input-button功能;据它所知,它是未定义的。 但是,如果您取出if(或禁用AlertMe()的部分呈现),当您点击UpdatePanel时,它将在完整回发时正常工作。

我希望它能用于部分回发,因为与页面的其他部分相比,这一切都是一小部分,我不希望每次切换视图时都进行完整的回发。
显然,ScriptManager甚至无法重新渲染ascx文件以进行可能的更改 要么btnSwitch不够智能,要么我缺少一个让它呈现ScriptManager的选项,所以我可以在客户端调用它的方法。

有人可能会建议的一个潜在答案是“你为什么不拿出javascript,把它放在自己的.js文件中,并让页面引用它以便控件可以使用它?”
这对我来说无法真正起作用,因为脚本块会对该单个控件实例进行一些初始化和修改,而不是对页面上的所有其他实例进行初始化和修改。

反过来,您可能还会担心如果我有多个控件实例,我最终会得到相同脚本的副本。并不是的;在任何给定的时间内,页面中只有一个输入模式,这只是我在两个单独的视图中有这两种模式,我让用户在它们之间切换。

感谢您阅读这篇文章=) 感谢任何帮助和意见。

2 个答案:

答案 0 :(得分:7)

要让您的脚本块正确支持partial page rendering,您必须使用ScriptManager.RegisterClientScriptBlock()方法在用户控件的PreRender阶段进行注册:

protected void Page_PreRender(object sender, EventArgs e)
{
    if (ShowAlertScript) {
        ScriptManager.RegisterClientScriptBlock(this,
            typeof(YourUserControl), "AlertScript",
            @"function AlertMe() 
              {
                  alert('Hello World!');
              }",
            true);
    }
}

(以上假设您在AutoEventWireup文件的@ Control指令中将true属性设置为ascx

此外,由于脚本是从用户控件注册的,但您的ScriptManager驻留在页面本身上,因此您可能需要在控件标记中添加<asp:ScriptManagerProxy>元素才能使上述工作正常工作

答案 1 :(得分:1)

UpdatePanel实际上通过对应于UpdatePanel控件的div上的AJAX框架设置innerHTML更改了其内容。

设置innerHTML时不执行脚本元素。

因此,在部分回发期间无法执行内联(即声明性)JS。