2013-01-22 62 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