44 votes

Validation de l'interface utilisateur WinForm

J'ai besoin de mettre en œuvre la validation des entrées tout au long de mon application winform. Il existe de nombreuses formes où les données peuvent être saisies et j'aimerais ne pas avoir à passer le contrôle par le contrôle de la forme et de créer isValid etc par article. Comment avez d'autres portaient avec cela?

Je vois que la plupart des postes liés à l'affaire avec le Web Apps et/ou de la mention d'Entreprise de la Bibliothèque de Validation de Bloc d'Application. Maintenant j'avoue que je n'ai pas bien étudié ELVAB mais il semble comme overkill pour ce que j'en ai besoin. Ma pensée est d'écrire une bibliothèque de classe avec les diverses exigences et passer une commande en tant que paramètre. J'ai déjà une Bibliothèque de fonctions RegEx pour des choses comme isValidZipCode et de telle sorte que peut être une place pour moi pour commencer.

Ce que j'aimerais avoir, c'est un bouton Valider qui onClick cycles à travers tous les contrôles sur le Formulaire de la Page, et procède à la validation nécessaire. Comment puis-je accomplir?

64voto

Matt Brunell Points 7120

La Validation est déjà intégré dans les WinForms de la bibliothèque.

Chaque Control-objet dérivé a deux événements nommés Validating et Validated. Aussi, il a une propriété appelée CausesValidation. Lorsque cette option est définie à true (c'est le cas par défaut), alors le contrôle participe à la validation. Sinon, il ne le fait pas.

La Validation se produit dans le cadre de mise au point. Lorsque vous vous concentrez hors de contrôle, la validation des événements sont déclenchés. En fait, les événements de focus sont placés dans un ordre spécifique. À partir de MSDN:

Lorsque vous changez le focus à l'aide de la clavier (TAB, MAJ+TAB, et ainsi de suite), en appelant le Sélectionner ou SelectNextControl méthodes, ou par réglage de la ContainerControl..::.ActiveControl propriété de la forme actuelle, l'accent des événements se produisent dans l'ordre suivant:

  1. Entrez
  2. GotFocus
  3. Laisser
  4. La validation
  5. Validé
  6. LostFocus

Lorsque vous changez le focus à l'aide de la de la souris ou en appelant la méthode Focus, l'accent événements se produisent dans la suite ordre:

  1. Entrez
  2. GotFocus
  3. LostFocus
  4. Laisser
  5. La validation
  6. Validé

Si la propriété CausesValidation est la valeur false, la Validation et la Validé événements sont supprimées.

Si l'Annuler propriété de l' CancelEventArgs est définie sur true dans le La validation de délégué d'événement, tous les événements qui serait survenue après l' La validation de l'événement sont supprimées.

Aussi un ContainerControl a une méthode appelée ValidateChildren() qui sera en boucle par le biais de contrôles contenus, et de les valider.

44voto

Bruce Points 281

Je me rends compte de ce fil est assez vieux, mais je pensais que je poste la solution je suis venu avec.

Le plus gros problème avec la validation sur WinForms est la validation n'est exécuté que lorsque le contrôle a "perdu le focus". Ainsi, l'utilisateur a de fait, cliquez à l'intérieur d'une zone de texte, puis cliquez quelque part d'autre pour la validation de routine à exécuter. C'est très bien si votre uniquement préoccupés par les données d'entrée est correcte. Mais cela ne fonctionne pas bien si vous essayez de faire en sorte qu'un utilisateur n'a pas laisser une zone de texte vide en sautant dessus.

Dans ma solution, lorsque l'utilisateur clique sur le bouton submit d'un formulaire, je vérifie chaque contrôle du formulaire (ou autre conteneur est spécifié) et utiliser la réflexion pour déterminer si une validation de la méthode est définie pour le contrôle. Si elle l'est, la méthode de validation est exécutée. Si une validation échoue, la routine renvoie une erreur et permet l'arrêt du processus. Cette solution fonctionne bien surtout si vous avez plusieurs formulaires pour valider.

1) il suffit de copier et coller cette section de code à votre projet. Nous sommes à l'aide de la Réflexion que vous avez besoin d'ajouter du Système.Refelection à votre utilisation de déclarations

class Validation
{
    public static bool hasValidationErrors(System.Windows.Forms.Control.ControlCollection controls)
    {
        bool hasError = false;

        // Now we need to loop through the controls and deterime if any of them have errors
        foreach (Control control in controls)
        {
            // check the control and see what it returns
            bool validControl = IsValid(control);
            // If it's not valid then set the flag and keep going.  We want to get through all
            // the validators so they will display on the screen if errorProviders were used.
            if (!validControl)
                hasError = true;

            // If its a container control then it may have children that need to be checked
            if (control.HasChildren)
            {
                if (hasValidationErrors(control.Controls))
                    hasError = true;
            }
        }
        return hasError;
    }

    // Here, let's determine if the control has a validating method attached to it
    // and if it does, let's execute it and return the result
    private static bool IsValid(object eventSource)
    {
        string name = "EventValidating";

        Type targetType = eventSource.GetType();

        do
        {
            FieldInfo[] fields = targetType.GetFields(
                 BindingFlags.Static |
                 BindingFlags.Instance |
                 BindingFlags.NonPublic);

            foreach (FieldInfo field in fields)
            {
                if (field.Name == name)
                {
                    EventHandlerList eventHandlers = ((EventHandlerList)(eventSource.GetType().GetProperty("Events",
                        (BindingFlags.FlattenHierarchy |
                        (BindingFlags.NonPublic | BindingFlags.Instance))).GetValue(eventSource, null)));

                    Delegate d = eventHandlers[field.GetValue(eventSource)];

                    if ((!(d == null)))
                    {
                        Delegate[] subscribers = d.GetInvocationList();

                        // ok we found the validation event,  let's get the event method and call it
                        foreach (Delegate d1 in subscribers)
                        {
                            // create the parameters
                            object sender = eventSource;
                            CancelEventArgs eventArgs = new CancelEventArgs();
                            eventArgs.Cancel = false;
                            object[] parameters = new object[2];
                            parameters[0] = sender;
                            parameters[1] = eventArgs;
                            // call the method
                            d1.DynamicInvoke(parameters);
                            // if the validation failed we need to return that failure
                            if (eventArgs.Cancel)
                                return false;
                            else
                                return true;
                        }
                    }
                }
            }

            targetType = targetType.BaseType;

        } while (targetType != null);

        return true;
    }

}

2) l'Utilisation de la norme de la Validation de l'événement sur tout le contrôle que vous souhaitez valider. Assurez-vous d'utiliser l'e.Annuler lors de la validation échoue!

private void txtLastName_Validating(object sender, CancelEventArgs e)
    {
        if (txtLastName.Text.Trim() == String.Empty)
        {
            errorProvider1.SetError(txtLastName, "Last Name is Required");
            e.Cancel = true;
        }
        else
            errorProvider1.SetError(txtLastName, "");
    }

3) de Ne pas sauter cette étape! Définir la AutoValidate bien sur la forme de EnableAllowFocusChange. Cela permettra de tabulation à un autre contrôle, même si la validation échoue.

4) Enfin, votre Bouton Soumettre méthode, l'appel de la méthode de Validation et de spécifier ce conteneur que vous souhaitez vérifier. Il peut être l'ensemble de la forme, ou tout simplement un conteneur sur la forme comme un Panneau ou d'un Groupe.

private void btnSubmit_Click(object sender, EventArgs e)
    {
        // the controls collection can be the whole form or just a panel or group
        if (Validation.hasValidationErrors(frmMain.Controls))
            return;

        // if we get here the validation passed
        this.close();
    }

Amusez-Vous Bien!

9voto

RS Conley Points 6268

Dans mon application, j'ai besoin de valider les dimensions, telles qu'elles sont saisies. La séquence que j'ai utilisé est le suivant

  1. L'utilisateur sélectionne le ou les types se déplace ensuite de contrôle.
  2. Le contrôle perd le focus et en informe la Vue de l'envoi de l'IDENTIFIANT et du entrée de texte.
  3. Le point de Vue des vérifications de la Forme de Programme (une classe implémentant une interface) créé le Formulaire et il passe le ID et l'entrée de texte
  4. La Forme du Programme renvoie une réponse.
  5. Si la Réponse est OK la Vue mises à jour de l'Entrée correcte de la Forme Classe.
  6. Si la Réponse est OK, l'Affichage indique la Forme à travers une Interface qu'il est OK pour déplacer l'axe à l'entrée suivante.
  7. Si la Réponse n'est pas OK, la Vue regarde la réponse et de l'aide de l' La forme de l'Interface indique la forme que de faire. Cela signifie généralement l'accent passe en arrière à l'entrée de la délinquance avec un message affiche, indiquant le l'utilisateur de ce qui s'est passé.

L'avantage de cette approche que la validation est centralisée en un seul endroit pour une Forme donnée de Programme. Je n'ai pas à aller modifier chaque contrôle ou même de réellement inquiéter sur les différents types de contrôles du formulaire. Chemin du retour quand j'ai conçu le logiciel, j'ai décidé de comment l'INTERFACE utilisateur d'aller travailler pour des zones de texte, listes déroulantes, les zones de liste déroulante, etc. Aussi différents niveaux de gravité est géré différemment.

La Vue se charge de les instruire de la Forme de ce faire par le biais de l'Interface. Comment il est réellement mis en œuvre est assurée par la Forme elle-même dans la mise en oeuvre de l'Interface. La Vue ne se soucie pas si le Formulaire est l'affichage de jaune d'avertissement et rouge pour les erreurs. Seulement qu'il gère ces deux niveaux. Plus tard, si une meilleure idée de l'affichage d'avertissement vs erreurs vient le long, je peux faire le changement dans la Forme elle-même plutôt de déblayage autour de avec la logique de la Vue ou de la validation de la Forme du Programme.

Vous êtes déjà à mi-chemin si vous envisagez de faire une classe afin de conserver votre logique de validation ainsi, vous obtenez le reste du chemin dans votre nouveau design.

4voto

Joel Coehoorn Points 190579

Je voudrais ne pas avoir à aller de contrôle en contrôle par formulaire et créer isValid etc. par article.

En tant que niveau, vous devrez définir ce que signifie être valid pour chaque contrôle, à moins que vous ne vouliez que le contrôle ait une valeur quelconque.

Cela dit, vous pouvez utiliser un composant ErrorProvider qui fonctionne assez bien.

3voto

Jamie Ide Points 28680

Nous avons eu de la chance avec Noogen ValidationProvider . C'est simple pour les cas simples (vérifications du type de données et champs obligatoires) et il est facile d'ajouter une validation personnalisée pour les cas plus complexes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X