web-dev-qa-db-fra.com

Comment passer Valider après avoir cliqué sur le bouton Annuler d'un formulaire

J'utilise C # . J'ai un Windows Form avec une zone d'édition et un bouton Annuler. La boîte d'édition a un code dans l'événement de validation. Le code est exécuté chaque fois que la zone d'édition perd le focus. Lorsque je clique sur le bouton Annuler, je souhaite simplement fermer le formulaire. Je ne veux aucune validation pour que la boîte d'édition soit exécutée. Comment cela peut-il être accompli?

Voici un détail important: si la validation échoue, alors 

            e.Cancel = true;

empêche de quitter le contrôle. 

Mais lorsqu'un utilisateur clique sur le bouton Annuler, le formulaire doit être fermé quoi qu'il arrive. comment cela peut-il être mis en œuvre?

41
user228985

Si la validation se produit lorsque la zone d'édition perd le focus, rien sur le bouton d'annulation ne va empêcher cela de se produire.

Toutefois, si la validation qui échoue empêche le bouton d'annulation de fonctionner, définissez la propriété CausesValidation du bouton sur false.

Référence: Button.CausesValidation property

45
Daniel Schaffer

De toute évidence, la propriété CausesValidation du bouton doit être définie sur false et l'événement de validation ne se produira jamais par un clic. Mais cela peut échouer si le contrôle parent du bouton a sa propriété CausesValidation définie sur true. La plupart du temps, les développeurs oublient ou oublient de modifier la propriété CausesValidation du contrôle conteneur (comme le contrôle du panneau). Définissez-le également sur False. Et cela devrait faire l'affaire.

31
Vimal Raj

J'avais de la difficulté à fermer mon formulaire, car la validation de certains contrôles l’arrêtait. J'avais défini le control.CausesValidation = false pour le bouton d'annulation et tous les parents du bouton d'annulation. Mais avait toujours des problèmes.

Il semblait que si l'utilisateur était en train de modifier un champ utilisant la validation et décidait d'abandonner (laissant le champ avec une entrée non valide), l'événement du bouton d'annulation était en cours de déclenchement, mais la fenêtre ne se fermait pas.

Ce problème a été résolu de la manière suivante dans l'événement de clic du bouton d'annulation:

private void btnCancel_Click(object sender, EventArgs e)
{
    // Stop the validation of any controls so the form can close.
    AutoValidate = AutoValidate.Disable;
    Close();
}
20
Ben

Définissez la propriété CausesValidation du bouton Annuler sur false.

18
womp

Aucune de ces réponses n'a vraiment fait le travail, mais la dernière réponse de ce fil fait. Fondamentalement, vous devez:

  1. Assurez-vous que le bouton Annuler (le cas échéant) a pour valeur .CausesValidation la valeur false
  2. Remplacez cette méthode virtuelle.

    protected override bool ProcessDialogKey(Keys keyData) {
        if (keyData == Keys.Escape) {
            this.AutoValidate = AutoValidate.Disable;
            CancelButton.PerformClick();
            this.AutoValidate = AutoValidate.Inherit;
            return true;
        }
        return base.ProcessDialogKey(keyData);
    }
    

Je n'ai pas vraiment répondu à cela, je me suis contenté de mentionner les deux types qui l'ont fait.

4
Wade Hatler

Définissez la propriété CausesValidation sur false.

4
Brandon

Définir CausesValidation sur false est la clé, mais cela ne suffit pas. Si CausesValidation est défini sur true sur le parent des boutons, l'événement de validation sera toujours appelé. Dans l'un de mes cas, j'avais un bouton d'annulation sur un panneau d'un formulaire; je devais donc définir CausesValidation = false sur le panneau ainsi que sur le formulaire. En fin de compte, je l'ai fait par programme, car c'était plus simple que de passer par toutes les formes ...

Control control = cancelButton;

while(control != null)
{
   control.CausesValidation = false;
   control = control.Parent;
}
2
Steve Sheldon

Une utilisation judicieuse de la propriété Control.CausesValidation vous aidera à atteindre vos objectifs.

2
Joe

Dans mon cas, sous la forme, je définis la propriété AutoValidate to EnableAllowFocusChange

1
Alecs

Juste au-dessus du code de validation dans la zone d'édition, ajoutez:

if (btnCancel.focused)
  {
     return;
  }

Ça devrait le faire.

1
TonyM

En utilisant l'assistant Visual Studio, vous pouvez le faire comme suit:

 enter image description here

1
Oscar Castiblanco

En complément de la réponse de Daniel Schaffer: si la validation a lieu lorsque la boîte de saisie perd le focus, vous pouvez interdire au bouton d'activer de contourner la validation locale et de quitter quand même.

public class UnselectableButton : Button
{
    public UnselectableButton()
    {
        this.SetStyle(ControlStyles.Selectable, false);
    }
}

ou si vous utilisez DevExpress:

this.simpleButtonCancel.AllowFocus = false;

Notez que cela changera l'expérience du clavier: l'onglet sera plus centré sur le bouton d'annulation.

1
Olivier de Rivoyre

Peut-être souhaitez-vous utiliser BackgroundWorker pour donner un peu de retard afin de décider si la validation doit être exécutée ou non. Voici l'exemple d'éviter la validation lors de la fermeture du formulaire.

    // The flag
    private bool _isClosing = false;

    // Action that avoids validation
    protected override void OnClosing(CancelEventArgs e) {
        _isClosing = true;
        base.OnClosing(e);
    }

    // Validated event handler
    private void txtControlToValidate_Validated(object sender, EventArgs e) {           
        _isClosing = false;
        var worker = new BackgroundWorker();
        worker.DoWork += worker_DoWork;
        worker.RunWorkerAsync();
        worker.RunWorkerCompleted += worker_RunWorkerCompleted;
    }

    // Do validation on complete so you'll remain on same thread
    void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
        if (!_isClosing)
            DoValidationHere();
    }

    // Give a delay, I'm not sure this is necessary cause I tried to remove the Thread.Sleep and it was still working fine. 
    void worker_DoWork(object sender, DoWorkEventArgs e) {
        Thread.Sleep(100);
    }
0
Adiono

C'est une vieille question, mais j'ai récemment rencontré ce problème et l'ai résolu de cette façon:

Premièrement, nous chargeons un UserControl dans un 'Shell' Form qui a un bouton de sauvegarde et d’annulation. Le UserControl hérite d'une interface (comme IEditView ) dotée de fonctions pour Enregistrer , Annuler , Valider et ToggleValidate

Dans la forme Shell, nous avons utilisé la souris entrer et laisser la souris comme suit:

    private void utbCancel_MouseEnter(object sender, EventArgs e)
    {
        ((Interface.IEdit)tlpMain.Controls[1]).ToggleValidate();
    }

    private void utbCancel_MouseLeave(object sender, EventArgs e)
    {
        ((Interface.IEdit)tlpMain.Controls[1]).ToggleValidate();
    }

Puis dans ToggleValidate (Dites un formulaire simple avec deux contrôles ... vous pouvez toujours parcourir une liste si vous le souhaitez), nous définissons le paramètre CausesValidation.

    public bool ToggleValidate()
    {
        uneCalcValue.CausesValidation = !uneCalcValue.CausesValidation;
        txtDescription.CausesValidation = !txtDescription.CausesValidation;

        return txtDescription.CausesValidation;
    }

J'espère que cela t'aides. 

0
melegant