Valider les données en utilisant DataAnnotations avec WPF & Entity Framework?

Existe-t-il un moyen de valider en utilisant DataAnnotations dans WPF & Entity Framework?

34
demandé sur Matthew Murdoch 2009-11-18 14:21:27

7 réponses

Vous pouvez utiliser les DataAnnotations.Classe Validator, comme décrit ici:

Http://johan.driessen.se/archive/2009/11/18/testing-dataannotation-based-validation-in-asp.net-mvc.aspx

Mais si vous utilisez une classe "buddy" pour les métadonnées, vous devez enregistrer ce fait avant de valider, comme décrit ici:

Http://forums.silverlight.net/forums/p/149264/377212.aspx

TypeDescriptor.AddProviderTransparent(
  new AssociatedMetadataTypeTypeDescriptionProvider(typeof(myEntity), 
    typeof(myEntityMetadataClass)), 
  typeof(myEntity));

List<ValidationResult> results = new List<ValidationResult>();
ValidationContext context = new ValidationContext(myEntity, null, null)
bool valid = Validator.TryValidateObject(myEntity, context, results, true);

[ajouté ce qui suit pour répondre à Shimmy commentaire]

, j'ai écrit une méthode générique pour implémenter la logique ci-dessus, de sorte que n'importe quel objet peut l'appeler:

// If the class to be validated does not have a separate metadata class, pass
// the same type for both typeparams.
public static bool IsValid<T, U>(this T obj, ref Dictionary<string, string> errors)
{
    //If metadata class type has been passed in that's different from the class to be validated, register the association
    if (typeof(T) != typeof(U))
    {
        TypeDescriptor.AddProviderTransparent(new AssociatedMetadataTypeTypeDescriptionProvider(typeof(T), typeof(U)), typeof(T));
    }

    var validationContext = new ValidationContext(obj, null, null);
    var validationResults = new List<ValidationResult>();
    Validator.TryValidateObject(obj, validationContext, validationResults, true);

    if (validationResults.Count > 0 && errors == null)
        errors = new Dictionary<string, string>(validationResults.Count);

    foreach (var validationResult in validationResults)
    {
        errors.Add(validationResult.MemberNames.First(), validationResult.ErrorMessage);
    }

    if (validationResults.Count > 0)
        return false;
    else
        return true;
}

Dans chaque objet qui doit être validé, j'ajoute un appel à cette méthode:

[MetadataType(typeof(Employee.Metadata))]
public partial class Employee
{
    private sealed class Metadata
    {
        [DisplayName("Email")]
        [Email(ErrorMessage = "Please enter a valid email address.")]
        public string EmailAddress { get; set; }
    }

    public bool IsValid(ref Dictionary<string, string> errors)
    {
        return this.IsValid<Employee, Metadata>(ref errors);
        //If the Employee class didn't have a buddy class,
        //I'd just pass Employee twice:
        //return this.IsValid<Employee, Employee>(ref errors);
    }
}
45
répondu Jeremy Gruenwald 2011-02-28 02:17:41

Je pense que ce qui manque à la réponse de Craigs est de savoir comment vérifier s'il y a des erreurs de validation. Ceci est dataannotation validation runner écrit par Steve Sanderson pour ceux qui veulent exécuter la vérification de validation dans la couche déférente puis la présentation ( http://blog.codeville.net/category/xval/, le code est dans l'exemple de projet):

public static IEnumerable<ErrorInfo> GetErrors(object instance)
{
    var metadataAttrib = instance.GetType().GetCustomAttributes
        (typeof(MetadataTypeAttribute), true).
            OfType<MetadataTypeAttribute>().FirstOrDefault();
    var buddyClassOrModelClass = 
        metadataAttrib != null ? 
        metadataAttrib.MetadataClassType : 
        instance.GetType();
    var buddyClassProperties = TypeDescriptor.GetProperties
        (buddyClassOrModelClass).Cast<PropertyDescriptor>();
    var modelClassProperties = TypeDescriptor.GetProperties
        (instance.GetType()).Cast<PropertyDescriptor>();

    return from buddyProp in buddyClassProperties
           join modelProp in modelClassProperties
               on buddyProp.Name equals modelProp.Name
           from attribute in buddyProp.Attributes.
               OfType<ValidationAttribute>()
           where !attribute.IsValid(modelProp.GetValue(instance))
           select new ErrorInfo(buddyProp.Name, 
               attribute.FormatErrorMessage(string.Empty), instance);
}

Je ne suis pas familier avec WPF (pas sûr s'il y a une solution prête à l'emploi pour votre question), mais peut-être que vous pouvez utiliser il.

En outre, il y a quelques commentaires sur son blog que dans certains cas, il ne parvient pas à évaluer la règle de validation correctement, mais il n'a jamais échoué pour moi.

4
répondu Misha N. 2010-08-10 03:20:30

Vous pourriez être intéressé par l'exemple d'application BookLibrary de Cadre D'Application WPF (WAF). Il fait exactement ce que vous demandez: en utilisant DataAnnotations dans WPF & Entity Framework.

3
répondu jbe 2011-02-06 07:28:59

J'ai eu la même question et a trouvé les idées suivantes:

1
répondu Guillaume Gros 2010-01-22 23:20:38

Utilisez une "classe buddy". Numéro 4 dans ce mode d'emploi .

0
répondu Craig Stuntz 2009-11-18 14:25:34

J'ai écrit un validateur basé sur Contributor qui inclut un contributeur de validation DataAnnotation et vérifie également les liaisons brisées (où l'Utilisateur a entré un type incorrect)

Http://adammills.wordpress.com/2010/07/21/mvvm-validation-and-type-checking/

0
répondu Adam Mills 2010-07-21 22:26:46

Dans. NET 4, Il existe un support de validation dans Entity-Framework utilisant cette extension, consultez: http://blogs.msdn.com/adonet/archive/2010/01/13/introducing-the-portable-extensible-metadata.aspx

Je ne suis pas sûr s'il utilise DataAnnotations tho.

Mise à JOUR
Je l'ai essayé avec VB.NET et cela n'a pas fonctionné, je pense qu'il ne supporte que les projets C#.

0
répondu Shimmy 2010-10-04 07:24:13