EntityFramework и DataAnnotations, ошибки не отображаются - PullRequest
2 голосов
/ 04 августа 2011

Я использую структуру сущностей и пытаюсь использовать аннотации данных для проверки.Я просмотрел несколько примеров в Google и нашел везде одинаковую структуру.Я следовал за этим, но по некоторым причинам мои ошибки не обнаруживаются в форме.Я знаю, что мне может потребоваться проверить свойства вручную с помощью класса Validator, но я не могу понять, где это сделать.Я знаю, что могу прослушать событие PropertyChanging, но оно передает только имя свойства, а не значение, которое должно быть назначено.У кого-нибудь есть идеи, как мне обойти это?

Заранее спасибо.

[MetadataType(typeof(Employee.MetaData))]
public partial class Employee
{
    private sealed class MetaData
    {
        [Required(ErrorMessage = "A name must be defined for the employee.")]
        [StringLength(50, ErrorMessage="The name must  be less than 50 characters long.")]
        public string Name { get; set; }

        [Required(ErrorMessage="A username must be defined for the employee.")]
        [StringLength(20, MinimumLength=3, ErrorMessage="The username must be between 3-20 characters long.")]
        public string Username { get; set; }

        [Required(ErrorMessage = "A password must be defined for the employee.")]
        [StringLength(20, MinimumLength = 3, ErrorMessage = "The password must be between 3-20 characters long.")]
        public string Password { get; set; }
    }
}

xaml

<fx:TextBox Width="250" Height="20" CornerRadius="5" BorderThickness="0" MaxLength="50" Text="{Binding Name, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True, NotifyOnValidationError=True}" />
<fx:TextBox Width="250" Height="20" CornerRadius="5" BorderThickness="0" MaxLength="20" Text="{Binding Username, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, NotifyOnValidationError=True}" />
<fx:PasswordBox Width="250" Height="20" CornerRadius="5" BorderThickness="0" MaxLength="20" Password="{Binding Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True, NotifyOnValidationError=True}" />

Редактировать: (реализован класс IDataErrorInfo на основе комментария Рэйчел)

public static class EntityHelper
{
    public static string ValidateProperty(object instance, string propertyName)
    {
        PropertyInfo property = instance.GetType().GetProperty(propertyName);
        object value = property.GetValue(instance, null);
        List<string> errors = (from v in property.GetCustomAttributes(true).OfType<ValidationAttribute>() where !v.IsValid(value) select v.ErrorMessage).ToList();
        return (errors.Count > 0) ? String.Join("\r\n", errors) : null;
    }
}

[MetadataType(typeof(Employee.MetaData))]
public partial class Employee:IDataErrorInfo
{
    private sealed class MetaData
    {
        [Required(ErrorMessage = "A name must be defined for the employee.")]
        [StringLength(50, ErrorMessage="The name must  be less than 50 characters long.")]
        public string Name { get; set; }

        [Required(ErrorMessage="A username must be defined for the employee.")]
        [StringLength(20, MinimumLength=3, ErrorMessage="The username must be between 3-20 characters long.")]
        public string Username { get; set; }

        [Required(ErrorMessage = "A password must be defined for the employee.")]
        [StringLength(20, MinimumLength = 3, ErrorMessage = "The password must be between 3-20 characters long.")]
        public string Password { get; set; }
    }

    public string Error { get { return String.Empty; } }
    public string this[string property]
    {
        get { return EntityHelper.ValidateProperty(this, property); }
    }

xaml

<fx:TextBox Width="250" Height="20" CornerRadius="5" BorderThickness="0" MaxLength="50" Text="{Binding Name, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />

1 Ответ

0 голосов
/ 13 декабря 2011

Я успешно реализовал подобный сценарий, и я настоятельно рекомендую вам посмотреть, как он был реализован в http://waf.codeplex.com/. В нем используется проверка аннотаций данных с помощью Entity Framework и WPF.

Одна существенная проблемаВы можете сделать с этой работой с Entity Framework то, что Validator аннотаций данных будет игнорировать ваши метаданные до тех пор, пока вы не добавите метаданные для EntityObject где-нибудь в своем коде перед проверкой:

TypeDescriptor.AddProviderTransparent(new 
    AssociatedMetadataTypeTypeDescriptionProvider(typeof(EntityObject)), 
    typeof(EntityObject));

Дополнительная информация: .NET 4Атрибут RTM MetadataType игнорируется при использовании Validator

Кроме того, я считаю, что ваши метаданные должны быть общедоступными, а не запечатанными.

Вот выдержка из DataErrorInfoSupport.cs, для быстрого ознакомления:1014 *

    /// <summary>
    /// Gets an error message indicating what is wrong with this object.
    /// </summary>
    /// <returns>An error message indicating what is wrong with this object. The default is an empty string ("").</returns>
    public string Error { get { return this[""]; } }

    /// <summary>
    /// Gets the error message for the property with the given name.
    /// </summary>
    /// <param name="memberName">The name of the property whose error message to get.</param>
    /// <returns>The error message for the property. The default is an empty string ("").</returns>
    public string this[string memberName]
    {
        get
        {
            List<ValidationResult> validationResults = new List<ValidationResult>();

            if (string.IsNullOrEmpty(memberName))
            {
                Validator.TryValidateObject(instance, new ValidationContext(instance, null, null), validationResults, true);
            }
            else
            {
                PropertyDescriptor property = TypeDescriptor.GetProperties(instance)[memberName];
                if (property == null)
                {
                    throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
                        "The specified member {0} was not found on the instance {1}", memberName, instance.GetType()));
                }
                Validator.TryValidateProperty(property.GetValue(instance),
                    new ValidationContext(instance, null, null) { MemberName = memberName }, validationResults);
            }

            StringBuilder errorBuilder = new StringBuilder();
            foreach (ValidationResult validationResult in validationResults)
            {
                errorBuilder.AppendInNewLine(validationResult.ErrorMessage);
            }

            return errorBuilder.ToString();
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...