2013-01-22 85 views
18

我有興趣使用WinForms應用程序和實體框架5設置客戶端驗證。我瞭解到,我可以實現IValidatableObject接口來執行和自定義驗證,以滿足每個需要實體。使用WinForms實體框架UI驗證

但是,由於我使用的是WinForms,因此在填寫表單時出現驗證錯誤時,我想使用ErrorProvider向用戶顯示一個很好的通知。是否可以使用IValidatableObject接口來實現此功能,還是需要在我的實體上實現IDataErrorInfo接口以使ErrorProvider正常工作?

如果您有更好的替代方案有任何其他建議,請讓我知道,我也樂意考慮這一點。

+0

的OP已要求EF 5,但希望它適用於EF 4.1的! –

+0

它適用於4.1. –

回答

5

有兩種選擇:

  • 與IValidateObject和IDataErrorInfo的擴展您的POCO類和驗證方法,提高用戶界面的錯誤。
  • 保存更改時調用驗證錯誤,並直接調用ErrorProvider,具體取決於哪個實體字段會生成驗證錯誤。

有關使用IValidateObject擴展poco類以及處理保存更改時出現驗證錯誤的示例,請參閱以下示例。

http://msdn.microsoft.com/en-us/data/gg193959.aspx

10

比方說你有一個實體,稱爲Car這個類包含了需要被驗證的財產。

public class Car 
{ 
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 

    // Accepted values have to be between 1 and 5. 
    public int NeedToBeValidatedRange { get; set; } 
} 

您必須爲我的示例中的所有實體創建一個基類,我將調用實體。

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.ComponentModel.DataAnnotations; 
using System.Linq; 

/// This is the base class for all entities and it provide a change notfication. 
public abstract class Entity : INotifyPropertyChanged 
{ 
    // Event fired when the property is changed! 
    public event PropertyChangedEventHandler PropertyChanged; 


    /// Called when int property in the inherited class is changed for ther others properties like (double, long, or other entities etc,) You have to do it. 
    protected void HandlePropertyChange(ref int value, int newValue, string propertyName) 
    { 
    if (value != newValue) 
    { 
     value = newValue; 
     this.Validate(propertyName); 
     this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 
    } 

    /// Validate the property 
    /// <returns> 
    /// The list of validation errors 
    /// </returns> 
    private ICollection<ValidationResult> PropertyValidator(string propertyName) 
    { 
    var validationResults = new Collection<ValidationResult>(); 
    PropertyDescriptor property = TypeDescriptor.GetProperties(this)[propertyName]; 

    Validator.TryValidateProperty(
     property.GetValue(this), 
     new ValidationContext(this, null, null) { MemberName = propertyName }, 
     validationResults); 

    return validationResults; 
    } 

    /// Validates the given property and return all found validation errors. 
    private void Validate(string propName) 
    { 
    var validationResults = this.PropertyValidator(propName); 
    if (validationResults.Count > 0) 
    { 
     var validationExceptions = validationResults.Select(validationResult => new ValidationException(validationResult.ErrorMessage)); 
     var aggregateException = new AggregateException(validationExceptions); 
     throw aggregateException; 
    } 
    } 
} 

,現在你得modfiy Car類,它應該是這樣的:

public class Car : Entity 
{ 
    private int id; 
    private int needToBeValidatedRange; 

    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int Id 
    { 
    get 
    { 
     return this.id; 
    } 
    set 
    { 
     this.HandlePropertyChange(ref this.id, value, "Id"); 
    } 
    } 

    [Range(1, 5)] 
    public int NeedToBeValidatedRange 
    { 
    get 
    { 
     return this.needToBeValidatedRange; 
    } 
    set 
    { 
     this.HandlePropertyChange(ref this.needToBeValidatedRange, value, "NeedToBeValidatedRange "); 
    } 
    } 
} 

某處在您創建的汽車實體的用戶界面:

Car car1 = new Car(); 
car1.NeedToBeValidatedRange = 3; // This will work! 

Car car2 = new Car(); 
car2.NeedToBeValidatedRange = 6; // This will throw ValidationException 
  • WPF支持非常好的ValidationException。
  • Winforms支持部分ValidationException,但現在您可以自由處理此問題。
+0

驗證程序如果訂單是'this.Validate(propertyName);驗證程序如何檢查**新值**; value = newValue;'?您需要將'value'與propname一起傳遞給驗證器,或者您需要先設置,然後驗證,然後在出錯時進行回滾。 – quetzalcoatl

+0

是的,你必須把價值,然後驗證我會改變代碼順序謝謝。 –

+1

此外,此方法僅允許您逐段驗證屬性。您將無法處理複雜的多字段驗證,因爲嘗試更改涉及的第一個屬性會導致失敗,因爲其他N個屬性尚未更改(並且自從第一個屬性拋出錯誤後無法生成)。這可以通過一些IEditXXX或IBeginXX/IEndXXX接口來解決,但會增加很多複雜性。我並不是說你提供的方法是錯誤的 - 在簡單的情況下它是好的/好的。我只是寫作警告,小心不要在某個時間點結束。 – quetzalcoatl