web-dev-qa-db-fra.com

ASP.NET CheckBox n’est pas déclenché d’événement CheckedChanged lorsqu’il désélectionne

J'ai un CheckBox sur un formulaire de contenu ASP.NET comme ceci:

<asp:CheckBox runat="server" ID="chkTest" AutoPostBack="true" OnCheckedChanged="chkTest_CheckedChanged" />

Dans mon code, j'ai la méthode suivante:

protected void chkTest_CheckedChanged(object sender, EventArgs e)
{
}

Lorsque je charge la page dans le navigateur et que je clique sur la case à cocher, la case est cochée, la page est postée en arrière et je peux voir que chkTest_CheckedChanged est appelé.

Lorsque je clique à nouveau sur la case à cocher, la case est décochée, mais la page est postée, mais chkTest_CheckedChanged n'est pas appelé.

Le processus est répétable, donc une fois que la case à cocher est décochée, sa vérification déclenchera l'événement.

J'ai View State désactivé dans Web.Config, l'activation de View State entraîne la disparition de ce problème. Que puis-je faire pour déclencher des événements fiables pendant que l'état d'affichage reste désactivé?

Mise à jour: Si je mets Checked="true" sur la balise du serveur, la situation est inversée et l'événement se déclenche lors de la désélection de CheckBox, mais pas l'inverse.

Mise à jour 2: J'ai remplacé la variable OnLoadComplete dans ma page et, de là, je peux confirmer que Request.Form["__EVENTTARGET"] est défini correctement sur l'ID de mon CheckBox.

26
Matt

L'implémentation d'un contrôle CheckBox personnalisé qui stocke la propriété Checked dans ControlState plutôt que ViewState résoudra probablement ce problème, même si la case à cocher contient AutoPostBack=false

Contrairement à ViewState, ControlState ne peut pas être désactivé et peut être utilisé pour stocker des données essentielles au comportement du contrôle.

Je n'ai pas encore d'environnement visuel studio à tester, mais cela devrait ressembler à ceci:

public class MyCheckBox : CheckBox
{
    private bool _checked;

    public override bool Checked { get { return _checked; } set { _checked = value; } }

    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        //You must tell the page that you use ControlState.
        Page.RegisterRequiresControlState(this);
    }

    protected override object SaveControlState()
    {
        //You save the base's control state, and add your property.
        object obj = base.SaveControlState();

        return new Pair (obj, _checked);
    }

    protected override void LoadControlState(object state)
    {
        if (state != null)
        {
            //Take the property back.
            Pair p = state as Pair;
            if (p != null)
            {
                base.LoadControlState(p.First);
                _checked = (bool)p.Second;
            }
            else
            {
                base.LoadControlState(state);
            }
        }
    }
}

plus d'infos ici .

19
Johnny5

Pour déclencher l'événement CheckedChanged, définissez les propriétés suivantes pour CheckBox, la propriété AutoPostBack doit être true et doit avoir une valeur par défaut cochée ou true.

AutoPostBack="true" Checked="false"
22
Able Alias

C'est un vieux message, mais je devais partager ma solution simple afin d'aider les autres personnes à la recherche de ce problème.

La solution est simple: Activez AutoPostBack.

        <asp:CheckBox id="checkbox1" runat="server"
                AutoPostBack="True" //<<<<------
                Text="checkbox"
                OnCheckedChanged="knowJobCBOX_CheckedChanged"/>
7
c0ldsh3ll

Il ne se déclenche pas car avec viewstate désactivé, le code du serveur ne sait pas que la case à cocher a été cochée auparavant. Par conséquent, il ne sait pas que l'état a changé. Pour autant que asp.net sache, le contrôle de case à cocher a été décoché avant la publication et est toujours décoché. Cela explique également le comportement inverse observé lors de la définition de Checked="true".

7
joshb

Je ne suis pas sûr, mais je suppose que ma solution ne fonctionne que pour .NET Framework 4.0:

Utilisez ViewStateMode = "Disabled" pour désactiver l’état d’affichage instable de EnableViewState="false". Cela évitera le même comportement, sauf que vous pouvez enregistrer un état d'affichage local.

Donc, sur votre case à cocher, définissez l'attribut ViewStateMode = "Enabled" et le problème sera résolu sans implémenter de case à cocher personnalisée.

6
Cristian Nicoleta

Je voulais ranger un peu les choses, alors je viens de passer un peu de temps à tester une solution pour cela.

joshb a bien expliqué pourquoi le CheckBox se comporte comme il le fait.

Comme je ne sais pas comment je me suis débrouillée cette année ou même si je le faisais (je ne me souviens pas de ce sur quoi je travaillais à l'époque pour vérifier), j'ai mis en place une solution simple.

public class CheckBox2 : CheckBox
{
    protected override bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)
    {
        bool isEventTarget = postCollection["__EVENTTARGET"] == UniqueID;
        bool hasChanged = base.LoadPostData(postDataKey, postCollection);
        hasChanged = hasChanged || isEventTarget;
        return hasChanged;
    }
}

Si vous enregistrez maintenant CheckBox2 dans votre page et utilisez-le à la place de vos CheckBox standard, l'événement CheckedChanged sera déclenché comme prévu avec ViewState désactivé et AutoPostBack activé.

La façon dont cela fonctionne permet à la CheckBox normale de procéder à la validation et à la vérification des modifications, mais effectue ensuite une vérification supplémentaire pour voir si elle était la cible de l'événement qui a provoqué la publication. S'il s'agissait de la cible, il renvoie true pour indiquer au cadre de déclencher l'événement CheckedChanged.

Edit: Veuillez noter que cela ne résout que le problème pour AutoPostBack sur la CheckBox. Si PostBack est invoqué à partir de quelque chose d'autre (un bouton, par exemple), l'événement CheckedChanged présente toujours le problème observé.

1
Matt

De plus: Recherchez les erreurs éventuelles dans la console JavaScript .

J'ai rencontré le même problème que décrit par OP, sauf qu'il ne s'est produit que dans Safari (checkbox fonctionnait correctement sous Chrome et Firefox). Lors de l'inspection de la console JavaScript, j'ai trouvé une erreur générée par un sélecteur jQuery mal formé.

Dans mon cas, j'avais $('a[id*=lbView') qui manquait d'un ] de fermeture. Cela a généré une erreur dans Safari mais, étonnamment, ni dans Chrome ni dans Firefox.

0
Mr.Z

La réponse la plus simple est de définir la variable ViewState pour ce contrôle.

Ajoutez simplement le EnableViewState="true" à la propriété AutoPostBack="true" dans la balise de case à cocher.

0
Scott Hurst

J'ai eu le même problème. J'ai passé beaucoup de temps dessus et l'ai finalement résolu.

Dans mon cas, la Checkbox était désactivée par défaut:

<asp:CheckBox ID="chkActive" runat="server" Enabled="false"/>

ViewState n'est pas chargé pour les contrôles désactivés ou invisibles . Supprimez donc Enabled="false" ou Visible="false" et cela fonctionnera comme s'il était spécifié Et bien sûr, ViewState ne devrait pas être désactivé.

0
algreat