Проверять данные с помощью DataAnnotations с WPF и Entity Framework? - PullRequest
35 голосов
/ 18 ноября 2009

Есть ли способ проверки с использованием DataAnnotations в WPF и Entity Framework?

Ответы [ 7 ]

45 голосов
/ 18 марта 2010

Вы можете использовать класс DataAnnotations.Validator, как описано здесь:

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

Но если вы используете класс «приятеля» для метаданных, вам нужно зарегистрировать этот факт перед проверкой, как описано здесь:

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);

[Добавлено следующее, чтобы ответить на комментарий Шимми]

Я написал обобщенный метод для реализации вышеупомянутой логики, чтобы любой объект мог вызывать его:

// 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;
}

В каждый объект, который необходимо проверить, я добавляю вызов к этому методу:

[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);
    }
}
4 голосов
/ 18 ноября 2009

Я думаю, что в ответе Крейгса не хватает того, как на самом деле проверить, есть ли ошибки проверки. Это средство проверки DataAnnotation, написанное Стивом Сандерсоном (Steve Sanderson) для тех, кто хочет выполнить проверку проверки на другом уровне, а затем на презентации (http://blog.codeville.net/category/xval/, код в примере проекта):

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);
}

Я не знаком с WPF (не уверен, есть ли какое-то готовое решение для вашего вопроса), но, возможно, вы можете его использовать.

Кроме того, в его блоге есть некоторые комментарии о том, что в некоторых случаях он не может правильно оценить правило проверки, но он никогда не подводил меня.

3 голосов
/ 06 февраля 2011

Вас может заинтересовать BookLibrary пример приложения WPF Application Framework (WAF) . Он делает именно то, что вы просите: используя DataAnnotations в WPF и Entity Framework.

1 голос
/ 23 января 2010

У меня был тот же вопрос и я нашел следующие идеи:

0 голосов
/ 22 июля 2010

Я написал валидатор на основе Contributor, который включает в себя участника валидации DataAnnotation, а также проверяет наличие сломанных привязок (когда пользователь ввел неправильный тип)

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

0 голосов
/ 09 февраля 2010

В .NET 4 есть поддержка валидации в Entity-Framework с использованием этого расширения, посмотрите: http://blogs.msdn.com/adonet/archive/2010/01/13/introducing-the-portable-extensible-metadata.aspx

Я не уверен, что он использует DataAnnotations tho.

UPDATE
Я попробовал это с VB.NET, и он не работал, я думаю, что он поддерживает только проекты на C #.

0 голосов
/ 18 ноября 2009

Используйте «класс приятеля». Номер 4 в это инструкции .

...