验证失败 ASP.NET - 显示的元素会更改可见性

ASP.NET validation fails - displayed elements change visibility

本文关键字:元素 可见性 显示 失败 ASP NET 验证      更新时间:2023-09-26

我有一个客户端Javascript,我在 ASP.NET 页面中使用,用于设置数据列表中几个项目的可见性。基本上,当项目 1 可见时,项目 2 应该隐藏,反之亦然。此代码还启用/禁用某些必需 ASP.NET 字段验证程序,具体取决于客户端周围字段的可见性。

除非我有 ASP.NET 验证错误,否则代码工作正常。验证失败时,字段将重置为其默认可见性(隐藏)。

我已经排除了这是回发,因为出现问题时我的服务器端断点不会被命中。这似乎是客户端脚本的问题。

服务器端修复已出来,因为页面永远不会回发。我想知道如何从 Javascript 的角度来看做到这一点?有没有办法在验证脚本触发时触发自定义代码?

我想过使用 cookie,但我认为这对我没有帮助,除非我可以挂接到验证事件。

代码如下...

function handleDropDown(e, a, b, c, v1, v2, h1, h2) {
    var i = parseInt(c) + 2;
    var x = parseInt(c) + 3;
    if (e.value == "Yes") {
        document.getElementById(i).style.display = "inline";
        document.getElementById(i).style.visibility = "visible";
        document.getElementById(x).style.display = "none";
        document.getElementById(x).style.visibility = "hidden";
        document.getElementById(a).focus();
        //Enable validator if needed
        var oVal1 = document.getElementById(v1);
        var oVal2 = document.getElementById(v2);
        var oVis1 = document.getElementById(h1);
        var oVis2 = document.getElementById(h2);
        ValidatorEnable(oVal1, true);
        if (oVis1 != null) {
            oVis1.value = "true";
        }
        ValidatorEnable(oVal2, false);
        if (oVis2 != null) {
            oVis2.value = "false";
        }
       }
    else if (e.value == "No") {
        document.getElementById(x).style.display = "inline";
        document.getElementById(x).style.visibility = "visible";
        document.getElementById(i).style.display = "none";
        document.getElementById(i).style.visibility = "hidden";
        document.getElementById(b).focus();
        //Enable validator if needed
        var oVal1 = document.getElementById(v1);
        var oVal2 = document.getElementById(v2);
        var oVis1 = document.getElementById(h1);
        var oVis2 = document.getElementById(h2);
        ValidatorEnable(oVal1, false);
        if (oVis1 != null) {
            oVis1.value = "false";
        }
        ValidatorEnable(oVal2, true);
        if (oVis2 != null) {
            oVis2.value = "true";
        }
    }
}

ASPX 标记代码段:**

             <span id="spTxtAnswer" class="required" visible="false" runat="server">*</span>
                        <asp:TextBox ID="txtAnswer" Text='<%# Bind("Answer") %>' runat="server" 
                                   TextMode="MultiLine" Height="76px" MaxLength="2000" Width="370px" Visible="false"  >
                        </asp:TextBox>
                        <asp:RequiredFieldValidator ID="valTextBox" ErrorMessage="This question is required." Enabled="false"
                        Display="Static" ControlToValidate="txtAnswer" runat="server" ValidationGroup="Request" />
                        <asp:RequiredFieldValidator ID="valAnswer" ControlToValidate="txtAnswer" ErrorMessage="<br />Other description is required."
                        Display="Static" enabled="false" runat="server"  ValidationGroup="Request" />
                        <span id="spDdlAnswer" class="required" visible="false" runat="server">*</span>
                        <asp:DropDownList ID="ddlAnswer" Visible="false" runat="server" />
                        <asp:RequiredFieldValidator ID="valDropDown" ControlToValidate="ddlAnswer" Enabled="false"
                        ErrorMessage="This field is required." Display="Static" runat="server"
                         InitialValue="(Select)"  ValidationGroup="Request" />
                        <asp:HiddenField ID="hfQuestionID" Value='<%# Bind("QuestionID") %>' runat="server" />
                        <asp:HiddenField ID="hfAnswer" Value='<%# Bind("Answer") %>' runat="server" />
                        <asp:HiddenField ID="hfRequired" Value='<%# Bind("Required") %>' runat="server" />
                        <asp:HiddenField ID="hfVisible" Value="false" runat="server" />
代码

隐藏代码片段:

TextBox tb1 = (TextBox)gridUserSupplierTypeQuestionsAndAnswers.Rows[rowIndex + 1].FindControl("txtAnswer");
            TextBox tb2 = (TextBox)gridUserSupplierTypeQuestionsAndAnswers.Rows[rowIndex + 2].FindControl("txtAnswer");
            RequiredFieldValidator rfv1 = (RequiredFieldValidator)gridUserSupplierTypeQuestionsAndAnswers.Rows[rowIndex + 1].FindControl("valTextBox");
            RequiredFieldValidator rfv2 = (RequiredFieldValidator)gridUserSupplierTypeQuestionsAndAnswers.Rows[rowIndex + 2].FindControl("valTextBox");
            HiddenField hf1 = (HiddenField)gridUserSupplierTypeQuestionsAndAnswers.Rows[rowIndex + 1].FindControl("hfVisible");
            HiddenField hf2 = (HiddenField)gridUserSupplierTypeQuestionsAndAnswers.Rows[rowIndex + 2].FindControl("hfVisible");
            ddl.Attributes.Add("onchange", "handleDropDown(this,'" + tb1.ClientID + "','" + tb2.ClientID + "','" + questionID + "','" + rfv1.ClientID + "','" + rfv2.ClientID + "'," + 
                "'" + hf1.ClientID + "','" + hf2.ClientID + "');");
            //When selected and viewing in edit mode, set the visibility during page load
            string script = "<script language='javascript'>";
            script += System.Environment.NewLine + "var el = document.getElementById('" + ddl.ClientID + "');";
            script += System.Environment.NewLine + "handleDropDown(el,'" + tb1.ClientID + "','" + tb2.ClientID + "','" + questionID + "','" + rfv1.ClientID + "','" + rfv2.ClientID + "');</script>";
            ClientScript.RegisterStartupScript(Page.GetType(),"startScript", script);

**

来自另一个堆栈溢出问题 (https://stackoverflow.com/a/11723794/704879):

"这就是问题所在:当验证器加载到页面上时,它会创建一些javascript来支持客户端验证。当您将验证器放置在默认情况下不可见的用户控件中,并且此用户控件位于更新面板中时,它不会正确创建该 JavaScript。这是解决方案:在更新面板之外,我在上面做了,使用虚拟验证组创建一个带有虚拟文本框的虚拟验证器,如下所示:"

功劳归于解决方案的原始海报(安东·贝列夫)。

我最终需要使用客户端脚本和cookie来设置可见性。我需要在回发后保留值,但在客户端读取它们,因此在这种情况下,viewstate 并不是一个真正的选择。

另一个相关问题是,当我尝试调用脚本以在IE10中设置字段可见性时,它总是在正文完成加载之前执行。我在母版页的正文标记中设置了调用,现在它工作正常。

我知道

这很旧,但是,以防万一其他人像我刚才那样遇到这种情况,我想提供Tim使用cookie跟踪客户端和服务器端之间的状态的答案的替代方案。

如果你有一些 JavaScript 需要能够读取一个值,例如特定控件是否已在客户端可见/隐藏,而不是使用 cookie,我建议以与 .NET 相同的方式创建自己的视图状态。

多年来,我看到许多同事试图将隐藏的字段控件放入他们的页面标记中,但这并不总是可靠的,因为 .NET 可以在重新加载视图状态时覆盖客户端值。 我使用的解决方案似乎工作非常可靠,并且不难设置。 这对于 Web 用户控件甚至服务器控件的工作方式完全相同。 这使服务器端和客户端能够跨回发访问值,并尊重客户端对可能发生的值的任何更改。

我下面的示例显示了布尔值、整数和字符串,但相同的方法可以用于任何可以序列化和反序列化为"字符串"值和从"字符串"值反序列化的数据类型。

public partial class MyPage : System.Web.UI.Page
{
    const string
        hdnFld1Nm = "hdnFld1",
        hdnFld2Nm = "hdnFld2",
        hdnFld3Nm = "hdnFld3";
    protected bool HiddenFieldValue1
    {
        get
        {
            object vsVal = this.ViewState["HiddenFieldValue1"];
            if (vsVal == null)
                return false;   // Whatever you want the 'default' value to be.
            else return (bool)vsVal;
        }
        set { this.ViewState["HiddenFieldValue1"] = value; }
    }
    protected int HiddenFieldValue2
    {
        get
        {
            object vsVal = this.ViewState["HiddenFieldValue2"];
            if (vsVal == null)
                return -1;  // Again, default value.
            else
                return (int)vsVal;
        }
        set { this.ViewState["HiddenFieldValue2"] = value; }
    }
    protected string HiddenFieldValue3
    {
        get { return (string)this.ViewState["HiddenFieldValue3"]; }
        set { this.ViewState["HiddenFieldValue3"] = value; }
    }
    protected void Page_Load(object sender, EventArgs e)
    {
        // For the boolean state, we'll consider any value other than "0" or NULL to be "true".
        this.HiddenFieldValue1 = (!string.IsNullOrEmpty(this.Request[hdnFld1Nm]) && this.Request.Form[hdnFld1Nm] != "0");
        // For the integer, we have to parse from the string value we get from the Form collection, and deal with the potential for "null" if no value was returned.
        string sHdnVal2 = this.Request.Form[hdnFld2Nm];
        int iHdnVal2;
        if (!string.IsNullOrEmpty(sHdnVal2) && !int.TryParse(sHdnVal2, out iHdnVal2))
            this.HiddenFieldValue2 = iHdnVal2;
        // Getting a string value back is easy.
        this.HiddenFieldValue3 = this.Request[hdnFld3Nm];
    }
    protected void Page_PreRender(object sender, EventArgs e)
    {
        // Before the page actually renders, we want to let the .NET page renderer know that we want these three hidden field values written to the output page.
        this.Page.ClientScript.RegisterHiddenField(hdnFld1Nm, this.HiddenFieldValue1 ? "1" : "0");  // Make sure you keep your boolean logic the same.
        this.Page.ClientScript.RegisterHiddenField(hdnFld2Nm, this.HiddenFieldValue2.ToString());   // Hidden fields can only store "string" values, so we have to "ToString" our int.
        this.Page.ClientScript.RegisterHiddenField(hdnFld3Nm, this.HiddenFieldValue3);
    }
}