Como faço para fazer uma caixa de seleção obrigatória em um formulário ASP.NET?

112

Eu fiz algumas pesquisas sobre isso, e encontrei várias respostas parciais, porém nada que me dê aquela impressão calorosa "esta é a maneira certa de fazer isso". Para responder à reclamação que ocorre com mais frequência contra esta pergunta: "as caixas de seleção podem ter dois estados legítimos - marcada e desmarcada", esta é uma caixa de seleção "Aceito os termos e condições ..." que deve ser marcada para concluir um registro, portanto, marcar a caixa é necessária do ponto de vista da lógica de negócios.

Forneça fragmentos de código prontos para cortar e colar completos com sua resposta! Eu sei que há várias peças para isso - o CustomValidator (presumivelmente), o code-behind, algum javascript e possivelmente uma verificação para IsValid, e a parte frustrante para mim é que em cada exemplo que vi, um desses peças estão faltando!

Bob Kaufman
fonte

Respostas:

216

função javascript para validação do lado do cliente (usando jQuery) ...

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

code-behind para validação do lado do servidor ...

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

Código ASP.Net para a caixa de seleção e 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>

e, finalmente, em seu postback - seja de um botão ou qualquer outro ...

if (Page.IsValid)
{
    // your code here...
}
Scott Ivey
fonte
Provavelmente estou fazendo algo errado. Vou continuar investigando até o fim, no entanto ControlToValidate = "<id-of-checkbox-control>" lança exceção "O controle <id-of-checkbox-control> referenciado pela propriedade ControlToValidate não pode ser validado." Que quebra o javascript etc.
Bob Kaufman
2
ahh certo. Apenas remova isso - CheckBox não implementa a interface correta para amarrá-lo. O validador ainda funcionará bem sem esse conjunto de propriedades. Vou atualizar meu exemplo de acordo.
Scott Ivey
2
O parâmetro CustomValidator para o nome da função javascript deve ser 'ClientValidationFunction', não 'OnClientValidate'. Consulte: msdn.microsoft.com/en-us/library/9eee01cx(v=VS.100).aspx
Chris
1
Eu sugeriria usar, em jQuery("#<%= MyCheckBox.ClientID %>")vez de jQuery(".AcceptedAgreement input:checkbox")ser mais explícito, qual elemento você está tentando afetar.
Jesse Webb
3
Inicialmente, não percebi que não há um atributo ControlToValidate. Incluir esse atributo causa uma exceção, portanto, uma palavra de aviso para outras pessoas que também podem não perceber isso.
MicrosoftAccessPros.com
19

Versão C # da resposta 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 por trás:

protected void CustomValidator1_ServerValidate(object source, ServerValidateEventArgs args)
{
    args.IsValid = CheckBox1.Checked;
}
John Rasch
fonte
obrigado pela versão C #. Bom uso de minimizar o código também.
andrewWinn
13

Se você quiser um validador verdadeiro que não dependa do jquery e lide com a validação do lado do servidor também (e você deve. A validação do lado do servidor é a parte mais importante), então aqui está um controle

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
fonte
Esta é a única resposta que funcionará em mais de um CheckBox em um formulário, ao invés de precisar de 1 função para cada objeto. Huzzah!
Haliphax
Muito obrigado. Eu precisava de uma maneira de fazer isso com vários controles renderizados dinamicamente. Impressionante.
schmosef
Embora a solução selecionada de Scott seja correta / válida, acredito que seja a solução mais completa. Esse controle personalizado deve ter sido incorporado à estrutura. Obrigado CirrusABS!
Gabe
5

A resposta de Scott funcionará para classes de caixas de seleção. Se você quiser caixas de seleção individuais, precisa ser um pouco mais furtivo. Se você estiver fazendo apenas uma caixa, é melhor fazê-lo com IDs. Este exemplo faz isso por meio de caixas de seleção específicas e não requer jQuery. É também um pequeno exemplo bom de como você pode colocar esses IDs de controle irritantes em seu Javascript.

O .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>

E o código por trás:

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
fonte
3

Normalmente, eu executo a validação no lado do 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>       
Roubar
fonte
Uma das melhores soluções, pois não Postback.
nu everest
O problema com isso é que a mensagem do validador não desaparece se você enviar, então tente e marque a caixa.
MC9000
-1

Maneira não 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 por trá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 quaisquer ações que você possa precisar (regras de negócios):

If Page.IsValid Then
   'do logic
End If 

Desculpe pelo código VB. . . você pode convertê-lo para C # se desejar. A empresa para a qual trabalho agora requer VB :(

andrewWinn
fonte
3
Isso não funcionará, pois você não pode anexar um validador à caixa de seleção! DOOOH!
0xDEAD BEEF