如何覆盖由Asp.Net UpdatePanel动态添加的Javascript函数?

5
我遇到了一个问题,我猜测它是由Javascript作用域问题和Microsoft Asp.Net客户端框架一起引起的。
由于这个问题所述的原因,我需要覆盖由Asp.Net的ScriptResource.axd提供的ValidatorConvert Javascript函数,并由其Validator服务器控件使用。
首先我会介绍如何使代码工作。然后我会展示一个我不能让它工作的场景。
这是一个简单的Asp.Net WebForm,其中包含一个验证控件:
<body>
<form id="form1" runat="server">
    <script type="text/javascript">
        function ValidatorConvert(op, dataType, val) {
            //>>Overwrite ValidatorConvert function.
            //>>Call to the original JS file will be below the form tag and above script tag
            return op.toString(); //<<Consider everything as valid (client side)
        }
    </script>
    <asp:ScriptManager runat="server"
        ID="Scriptmanager1" 
        allowcustomerrorsredirect="true" 
        asyncpostbackerrormessage="Operation cannot be executed."
        asyncpostbacktimeout="90"
        enablepartialrendering="true"
        enablescriptglobalization="true" 
        enablescriptlocalization="true" 
        supportspartialrendering="true" 
        scriptmode="Inherit"></asp:ScriptManager>
    <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
    <asp:CompareValidator
        ID="CompareValidator1"
        runat="server"
        ErrorMessage="Ops, not an integer"
        Operator="DataTypeCheck"
        Type="Integer"
        ControlToValidate="TextBox1"></asp:CompareValidator>
    <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
</form>
</body>

现在,当asp.net渲染表单时,它会以某种方式检测到页面上有一个可见的验证控件。因此,在我的脚本标签正下方和表单正上方,将调用客户端JS进行验证器。这个JS文件将有一个ValidatorConvert函数,它将被我的函数覆盖。
现在,这里有一个场景,这种方法不起作用。下面是一个稍微不同的WebForm:
<body>
<form id="form1" runat="server">
    <asp:ScriptManager runat="server"
        ID="Scriptmanager1" 
        allowcustomerrorsredirect="true" 
        asyncpostbackerrormessage="Operation cannot be executed."
        asyncpostbacktimeout="90"
        enablepartialrendering="true"
        enablescriptglobalization="true" 
        enablescriptlocalization="true" 
        supportspartialrendering="true" 
        scriptmode="Inherit"></asp:ScriptManager>
    <asp:UpdatePanel ID="UpdatePanel1" runat="server">
        <ContentTemplate>
            <asp:MultiView ID="MultiView1" runat="server" ActiveViewIndex="0">
                <asp:View ID="View1" runat="server">
                    <asp:Button ID="ButtonShowInput" runat="server" Text="Show Input     Field" CausesValidation="false" OnClick="ButtonShowInput_Click" />
                </asp:View>
                <asp:View ID="View2" runat="server">
                    <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
                    <asp:CompareValidator
                        ID="CompareValidator1"
                        runat="server"
                        ErrorMessage="Ops, not an integer"
                        Operator="DataTypeCheck"
                        Type="Integer"
                        ControlToValidate="TextBox1"></asp:CompareValidator>
                    <asp:Button ID="Button1" runat="server" Text="Button"   OnClick="Button1_Click" />
                </asp:View>
            </asp:MultiView>
        </ContentTemplate>
    </asp:UpdatePanel>
</form>
</body>

现在我有一个UpdatePanel里面包含一个MultiView。页面加载时,可见的视图是只有一个按钮的第一个视图。当按下此按钮时,它将显示具有验证控件的第二个视图。由于这是在UpdatePanel内部,因此将使用AJAX完成此操作。
现在,在呈现表单时,默认情况下不会显示验证控件。因此,链接到javascript文件(ScriptResource.axd)将根本不会放置在页面上!
但是当按下按钮并且验证程序可见时,链接将被动态添加。
问题是,此链接由asp.net框架放置在head标记中。
即使我的函数仍然在原始函数的层次结构下定义,我的函数也没有被调用。
我尝试将我的函数放置在不同的位置,包括head标记,但似乎也不起作用。似乎最后定义的函数被视为有效。
那么,在第二种情况下,如何覆盖函数?此外,是否有适用于两种情况的单个解决方案?
感谢您提前花费时间。

你尝试过在服务器端通过 ScriptManager.RegisterStartupScriptScriptManager.RegisterClientScriptBlock 在按钮点击时以编程方式生成JS函数吗? - Yuriy Galanter
Yuriy,谢谢你的建议。RegisterClientScriptBlock没有起作用。然而,在测试您的建议时,我尝试将脚本块放置在UpdatePanel内部。不知何故,这样做就奏效了。无论标记位于UpdatePanel的何处都没有关系。我仍在研究这个问题,以了解背后的原因。但我想最终我可以有一个定义我的函数"OnPageReady"的MasterPage,然后尝试在Ajax执行后设置它。这可能对单个应用程序的两种情况都有帮助。我会测试并稍后在此发布。谢谢。 - Rodrigo Lira
很酷,很高兴你找到了解决方案。祝你好运! - Yuriy Galanter
1个回答

2

感谢Yuriy的贡献,我得以想出一个解决方案。

基本上,我创建了一段代码,用于在页面首次加载时定义我的函数。此外,我注册了自定义函数,以便在每个ajax请求后重新定义我的函数。由于我将此代码放在MasterPage上,所以能够使其适用于整个应用程序。

以下是代码:

MasterPage.aspx是一个简单的Html页面,其中包含了ContentPlaceHolders和ScriptManager,位于form标签正下方。另外,我还需要在页面顶部(head标签)放置对“Utils.js”的引用。

MasterPage.aspx.cs

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        if (!Page.ClientScript.IsStartupScriptRegistered("jsDefineFunction"))
            Page.ClientScript.RegisterStartupScript(Page.GetType(), "jsDefineFunction", "defineValidationFunction();", true);

        if (!Page.ClientScript.IsStartupScriptRegistered("jsDefineEndRequestFunction"))
            Page.ClientScript.RegisterStartupScript(Page.GetType(), "jsDefineEndRequestFunction", "Sys.WebForms.PageRequestManager.getInstance().add_endRequest(defineValidationFunction);", true);
    }
}

Utils.js

function defineValidationFunction() {
    var ValidatorConvert = function (op, dataType, val) {
            //>>Consider everything as valid (client side)
            return op.toString();
        }
}

有了这个,我的代码适用于所有使用主页面的页面。代码将不断用我的函数覆盖验证函数。有一点点开销,但我找不到其他方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接