114 votes

Détection des erreurs de validation WPF

Dans WPF, vous pouvez configurer la validation basée sur des erreurs jeté dans votre Couche de Données lors de la Liaison de Données à l'aide de la ExceptionValidationRule ou DataErrorValidationRule.

Supposons que vous avez eu un tas de contrôles mis en place cette façon, et vous avez eu un bouton Enregistrer. Lorsque l'utilisateur clique sur le bouton Enregistrer, vous devez vous assurer que il n'y a pas des erreurs de validation avant de procéder à l'enregistrement. Si il y a des erreurs de validation, vous voulez crier à eux.

Dans WPF, comment pouvez-vous savoir si l'un de vos Données à des contrôles Liés avoir des erreurs de validation de jeu?

135voto

Dean Points 756

Ce post était extrêmement utile. Merci à tous ceux qui ont contribué. Voici une version de LINQ que vous aimerez ou détesterez.

         private void CanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = IsValid(sender as DependencyObject);
    }

    private bool IsValid(DependencyObject obj)
    {
        // The dependency object is valid if it has no errors, 
        //and all of its children (that are dependency objects) are error-free.
        return !Validation.GetHasError(obj) &&
            LogicalTreeHelper.GetChildren(obj)
            .OfType<DependencyObject>()
            .All(IsValid);
    }
 

47voto

aogan Points 1512

Le code suivant (tiré du livre Programming WPF de Chris Sell & Ian Griffiths) valide toutes les règles de liaison sur un objet de dépendance et ses enfants:

 public static class Validator
{

    public static bool IsValid(DependencyObject parent)
    {
        // Validate all the bindings on the parent
        bool valid = true;
        LocalValueEnumerator localValues = parent.GetLocalValueEnumerator();
        while (localValues.MoveNext())
        {
            LocalValueEntry entry = localValues.Current;
            if (BindingOperations.IsDataBound(parent, entry.Property))
            {
                Binding binding = BindingOperations.GetBinding(parent, entry.Property);
                foreach (ValidationRule rule in binding.ValidationRules)
                {
                    ValidationResult result = rule.Validate(parent.GetValue(entry.Property), null);
                    if (!result.IsValid)
                    {
                        BindingExpression expression = BindingOperations.GetBindingExpression(parent, entry.Property);
                        System.Windows.Controls.Validation.MarkInvalid(expression, new ValidationError(rule, expression, result.ErrorContent, null));
                        valid = false;
                    }
                }
            }
        }

        // Validate all the bindings on the children
        for (int i = 0; i != VisualTreeHelper.GetChildrenCount(parent); ++i)
        {
            DependencyObject child = VisualTreeHelper.GetChild(parent, i);
            if (!IsValid(child)) { valid = false; }
        }

        return valid;
    }

}
 

Vous pouvez appeler cela dans le gestionnaire d’événements de clic du bouton de sauvegarde comme ceci dans votre page / fenêtre

 private void saveButton_Click(object sender, RoutedEventArgs e)
{

  if (Validator.IsValid(this)) // is valid
   {

    ....
   }
}
 

32voto

H-Man2 Points 1919

Le code affiché ne fonctionnait pas pour moi lors de l'utilisation d'un ListBox. Je l'ai réécrit et maintenant ça marche:

 public static bool IsValid(DependencyObject parent)
{
    if (Validation.GetHasError(parent))
        return false;

    // Validate all the bindings on the children
    for (int i = 0; i != VisualTreeHelper.GetChildrenCount(parent); ++i)
    {
        DependencyObject child = VisualTreeHelper.GetChild(parent, i);
        if (!IsValid(child)) { return false; }
    }

    return true;
}
 

7voto

Matthias Loerke Points 111

En plus de l'excellente implémentation LINQ de Dean, je me suis amusé à intégrer le code dans une extension de DependencyObjects:

 public static bool IsValid(this DependencyObject instance)
{
   // Validate recursivly
   return !Validation.GetHasError(instance) &&  LogicalTreeHelper.GetChildren(instance).OfType<DependencyObject>().All(child => child.IsValid());
}
 

Cela le rend extrêmement agréable compte tenu de la réutilisation.

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