2011-08-04 46 views
2

我正在使用實體框架並嘗試使用數據註釋進行驗證。我在谷歌上查找了幾個例子,並且在任何地方都找到了相同的結構。我跟着它,但由於某種原因,我的錯誤沒有顯示在窗體中。我知道,我可能必須使用Validator類來手動驗證屬性,但我無法弄清楚在哪裏做。我知道我可以聽到PropertyChanging事件,但只傳遞屬性的名稱,而不是將要分配的值。任何人有任何想法我可以解決這個問題?EntityFramework和DataAnnotations,錯誤未顯示

在此先感謝。

[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

神聖的婚姻殿堂!你最好開始使用不同的方法來實現你的驗證邏輯,因爲當你繼續這種方式時,你將會走向維護夢魘。爲什麼不使用DataAnnotations或驗證應用程序塊並將其與「DataErrorInfoBase」類集成。看看這種整合的例子[這裏](http://bit.ly/crLXAz)。 – Steven

+0

@Steven我正在使用EntityFramework,所以生成的實體從'EntityObject'派生,所以我不能添加另一個基類。您認爲可能有幫助的其他任何鏈接?謝謝。 –

+1

看我的[更新](http://bit.ly/crLXAz)。它描述瞭如何用EF 3.5做到這一點。 – Steven

回答

0

我已經成功實現了類似的場景,我強烈建議你看看它是如何在http://waf.codeplex.com/中實現的。它使用實體框架和WPF使用數據批註驗證。

你可能有使實體框架這項工作的一個顯著的問題是,數據註釋驗證器會忽略你的元數據,直到您EntityObject地方在你的代碼驗證之前添加元數據:

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

其他信息: .NET 4 RTM MetadataType attribute ignored when using Validator

另外,我認爲你的元數據應該是公開的而不是密封的。

這裏是DataErrorInfoSupport.cs的摘錄,爲快速參考:

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