¿Cómo hago necesaria una casilla de verificación en un formulario ASP.NET?

112

Hice una búsqueda sobre esto y encontré varias respuestas parciales, sin embargo, nada que me dé ese cálido y difuso "esta es la manera correcta de hacer esto". Para responder a la queja más frecuente contra esta pregunta: "las casillas de verificación pueden tener dos estados legítimos: marcada y desmarcada", esta es una casilla de verificación "Acepto los términos y condiciones ..." que debe marcarse para completar un registro, por lo tanto, se requiere marcar la casilla desde el punto de vista de la lógica empresarial.

¡Proporcione fragmentos de código completos listos para cortar y pegar con su respuesta! Sé que hay varias piezas en esto: el CustomValidator (presumiblemente), el código subyacente, algo de javascript y posiblemente una verificación de IsValid, y la parte frustrante para mí es que en cada ejemplo que he visto, uno de estos elementos críticos faltan piezas!

Bob Kaufman
fuente

Respuestas:

216

función javascript para la validación del lado del cliente (usando jQuery) ...

function CheckBoxRequired_ClientValidate(sender, e)
{
    e.IsValid = jQuery(".AcceptedAgreement input:checkbox").is(':checked');
}

código subyacente para la validación del lado del servidor ...

protected void CheckBoxRequired_ServerValidate(object sender, ServerValidateEventArgs e)
{
    e.IsValid = MyCheckBox.Checked;
}

Código ASP.Net para la casilla de verificación y el validador ...

<asp:CheckBox runat="server" ID="MyCheckBox" CssClass="AcceptedAgreement" />
<asp:CustomValidator runat="server" ID="CheckBoxRequired" EnableClientScript="true"
    OnServerValidate="CheckBoxRequired_ServerValidate"
    ClientValidationFunction="CheckBoxRequired_ClientValidate">You must select this box to proceed.</asp:CustomValidator>

y finalmente, en su devolución de datos, ya sea desde un botón o lo que sea ...

if (Page.IsValid)
{
    // your code here...
}
Scott Ivey
fuente
Probablemente estoy haciendo algo mal. Continuaré investigando al final, sin embargo ControlToValidate = "<id-of-checkbox-control>" arroja una excepción "El control <id-of-checkbox-control> al que hace referencia la propiedad ControlToValidate no se puede validar". Lo que rompe el javascript, etc.
Bob Kaufman
2
ahh, cierto. Simplemente elimínelo: CheckBox no implementa la interfaz correcta para atarlo. El validador seguirá funcionando bien sin esa propiedad establecida. Actualizaré mi ejemplo en consecuencia.
Scott Ivey
2
El parámetro CustomValidator para el nombre de la función de JavaScript debe ser 'ClientValidationFunction', no 'OnClientValidate'. Ver: msdn.microsoft.com/en-us/library/9eee01cx(v=VS.100).aspx
Chris
1
Sugeriría usar en jQuery("#<%= MyCheckBox.ClientID %>")lugar de jQuery(".AcceptedAgreement input:checkbox")ser más explícito en qué elemento está intentando afectar.
Jesse Webb
3
Inicialmente no noté que no hay un atributo ControlToValidate. La inclusión de este atributo provoca una excepción, por lo que una advertencia para otros que también pueden pasarlo por alto.
MicrosoftAccessPros.com
19

Versión C # de la respuesta de andrew:

<asp:CustomValidator ID="CustomValidator1" runat="server" 
        ErrorMessage="Please accept the terms..." 
        onservervalidate="CustomValidator1_ServerValidate"></asp:CustomValidator>
    <asp:CheckBox ID="CheckBox1" runat="server" />

Código detrás:

protected void CustomValidator1_ServerValidate(object source, ServerValidateEventArgs args)
{
    args.IsValid = CheckBox1.Checked;
}
John Rasch
fuente
gracias por la versión C #. Buen uso de minimizar el código también.
andrewWinn
13

Si desea un verdadero validador que no se base en jquery y maneje la validación del lado del servidor también (y debería hacerlo. La validación del lado del servidor es la parte más importante) entonces aquí hay un control

public class RequiredCheckBoxValidator : System.Web.UI.WebControls.BaseValidator
{
    private System.Web.UI.WebControls.CheckBox _ctrlToValidate = null;
    protected System.Web.UI.WebControls.CheckBox CheckBoxToValidate
    {
        get
        {
            if (_ctrlToValidate == null)
                _ctrlToValidate = FindControl(this.ControlToValidate) as System.Web.UI.WebControls.CheckBox;

            return _ctrlToValidate;
        }
    }

    protected override bool ControlPropertiesValid()
    {
        if (this.ControlToValidate.Length == 0)
            throw new System.Web.HttpException(string.Format("The ControlToValidate property of '{0}' is required.", this.ID));

        if (this.CheckBoxToValidate == null)
            throw new System.Web.HttpException(string.Format("This control can only validate CheckBox."));

        return true;
    }

    protected override bool EvaluateIsValid()
    {
        return CheckBoxToValidate.Checked;
    }

    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);

        if (this.Visible && this.Enabled)
        {
            System.Web.UI.ClientScriptManager cs = this.Page.ClientScript;
            if (this.DetermineRenderUplevel() && this.EnableClientScript)
            {
                cs.RegisterExpandoAttribute(this.ClientID, "evaluationfunction", "cb_verify", false);
            }
            if (!this.Page.ClientScript.IsClientScriptBlockRegistered(this.GetType().FullName))
            {
                cs.RegisterClientScriptBlock(this.GetType(), this.GetType().FullName, GetClientSideScript());
            } 
        }
    }

    private string GetClientSideScript()
    {
        return @"<script language=""javascript"">function cb_verify(sender) {var cntrl = document.getElementById(sender.controltovalidate);return cntrl.checked;}</script>";
    }
}
CirrusABS
fuente
Esta es la única respuesta que funcionará en más de un CheckBox en un formulario, en lugar de necesitar 1 función por cada objeto. ¡Hurra!
haliphax
Muchas gracias. Necesitaba una forma de hacer esto con múltiples controles renderizados dinámicamente. Increíble.
schmosef
Si bien la solución seleccionada de Scott es correcta / válida, creo que esta es la solución más completa. Este control personalizado debería haberse integrado en el marco. ¡Gracias CirrusABS!
Gabe
5

La respuesta de Scott funcionará para clases de casillas de verificación. Si desea casillas de verificación individuales, debe ser un poco más astuto. Si solo está haciendo un cuadro, es mejor hacerlo con ID. Este ejemplo lo hace mediante casillas de verificación específicas y no requiere jQuery. También es un pequeño ejemplo de cómo puede obtener esos molestos ID de control en su Javascript.

El .ascx:

<script type="text/javascript">

    function checkAgreement(source, args)
    {                
        var elem = document.getElementById('<%= chkAgree.ClientID %>');
        if (elem.checked)
        {
            args.IsValid = true;
        }
        else
        {        
            args.IsValid = false;
        }
    }

    function checkAge(source, args)
    {
        var elem = document.getElementById('<%= chkAge.ClientID %>');
        if (elem.checked)
        {
            args.IsValid = true;
        }
        else
        {
            args.IsValid = false;
        }    
    }

</script>

<asp:CheckBox ID="chkAgree" runat="server" />
<asp:Label AssociatedControlID="chkAgree" runat="server">I agree to the</asp:Label>
<asp:HyperLink ID="lnkTerms" runat="server">Terms & Conditions</asp:HyperLink>
<asp:Label AssociatedControlID="chkAgree" runat="server">.</asp:Label>
<br />

<asp:CustomValidator ID="chkAgreeValidator" runat="server" Display="Dynamic"
    ClientValidationFunction="checkAgreement">
    You must agree to the terms and conditions.
    </asp:CustomValidator>

<asp:CheckBox ID="chkAge" runat="server" />
<asp:Label AssociatedControlID="chkAge" runat="server">I certify that I am at least 18 years of age.</asp:Label>        
<asp:CustomValidator ID="chkAgeValidator" runat="server" Display="Dynamic"
    ClientValidationFunction="checkAge">
    You must be 18 years or older to continue.
    </asp:CustomValidator>

Y el código subyacente:

Protected Sub chkAgreeValidator_ServerValidate(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ServerValidateEventArgs) _
Handles chkAgreeValidator.ServerValidate
    e.IsValid = chkAgree.Checked
End Sub

Protected Sub chkAgeValidator_ServerValidate(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ServerValidateEventArgs) _
Handles chkAgeValidator.ServerValidate
    e.IsValid = chkAge.Checked
End Sub
jorelli
fuente
3

Normalmente realizo la validación en el lado del cliente:

<asp:checkbox id="chkTerms" text=" I agree to the terms" ValidationGroup="vg" runat="Server"  />
<asp:CustomValidator id="vTerms"
                ClientValidationFunction="validateTerms" 
                ErrorMessage="<br/>Terms and Conditions are required." 
                ForeColor="Red"
                Display="Static"
                EnableClientScript="true"
                ValidationGroup="vg"
                runat="server"/>

<asp:Button ID="btnSubmit" OnClick="btnSubmit_Click" CausesValidation="true" Text="Submit" ValidationGroup="vg" runat="server" />

<script>
    function validateTerms(source, arguments) {
        var $c = $('#<%= chkTerms.ClientID %>');
        if($c.prop("checked")){
            arguments.IsValid = true;
        } else {
            arguments.IsValid = false;
        }
    }
</script>       
Robar
fuente
Una de las mejores soluciones ya que no Postback.
nu everest
El problema con esto es que el mensaje del validador no desaparece si lo envía, luego intente marcar la casilla.
MC9000
-1

Forma no javascript. . página aspx:

 <form id="form1" runat="server">
<div>
    <asp:CheckBox ID="CheckBox1" runat="server" />
    <asp:CustomValidator ID="CustomValidator1"
        runat="server" ErrorMessage="CustomValidator" ControlToValidate="CheckBox1"></asp:CustomValidator>
</div>
</form>

Código detrás:

Protected Sub CustomValidator1_ServerValidate(ByVal source As Object, ByVal args As System.Web.UI.WebControls.ServerValidateEventArgs) Handles CustomValidator1.ServerValidate
    If Not CheckBox1.Checked Then
        args.IsValid = False
    End If
End Sub

Para cualquier acción que pueda necesitar (reglas comerciales):

If Page.IsValid Then
   'do logic
End If 

Perdón por el código VB. . . puede convertirlo a C # si le place. La empresa para la que trabajo ahora requiere VB :(

AndrewWinn
fuente
3
¡Esto no funcionará, ya que no puede adjuntar el validador a la casilla de verificación! DOOOH!
0xDEAD BEEF