如何在绑定到DbSet <。>本地?</t>时处理WPF中的验证

时间:2013-08-02 13:28:25

标签: wpf entity-framework entity-framework-5 idataerrorinfo inotifydataerrorinfo

DbSet<T>.Local提供了一个可以绑定到WPF控件的ObservableCollection。就我而言,我将它绑定到网格。

如果我使用的是视图模型,我会让它们实现INotifyDataErrorInfoIDataErrorInfo,然后编写Fluent Validation验证器来处理验证。

但是在这里我通过DbSet<T>.Local绑定了模型。我该如何处理验证?

我应该在模型上实施INotifyDataErrorInfo还是IDataErrorInfo

或者有其他选择吗?

2 个答案:

答案 0 :(得分:1)

如果您的应用程序是胖客户端,意味着应用程序的所有层都在一台物理机器上,那么您应该在模型上实现IDataErrorInfo

另一方面,如果您的应用程序是一个瘦的多累应用程序,意味着您的模型是在服务器上实现的,并且您正在使用WPF桌面应用程序与服务器端代码进行通信,那么您应该实现{{1 }}

答案 1 :(得分:1)

是的,我认为在POCO模型中实现IValidatableObject的实现是有意义的。 您可能已经注意到public ObservableCollection<TEntity> Local { get; }

有几种方法可以做到这一点。所以做了一些功课。

As some background , might be useful

Then check this out

所以我们知道EF有触发验证的概念。

Configuration.ValidateOnSaveEnabled = true; 

EF也会拨打IEnumerable<ValidationResult> ValidateInstance();

来自界面IValidatableObject

如果您的实体POCO实施IValidatableObject

EF将在SAve上触发验证。 您还可以在需要时轻松触发验证。

这一切都与UoW概念完全相关。

 public IEnumerable<DbEntityValidationResult> GetDbValidationErrors() { return 
        Context.GetValidationErrors(); }   // Standard Context call get the problems

可以使用      catch(Exception ex){....         var x = GetDbValidationErrors();       //....

所以我认为你走在正确的轨道上......

编辑:添加SAMPLE POCOBase并演示触发器验证。

public interface IFBaseObject : IValidatableObject {
    // a POCO object must implement the VALIDATE method from    IValidatableObject
    bool IsValidInstance();
    IEnumerable<ValidationResult> ValidateInstance();

}

public abstract class BaseObject : IFBaseObject {

     // .... base object stuff removed....

    /// <summary>
    /// Get called every a Validation is trigger on an object.  Here we return and Empty resultset to start with.
    /// If you override ALWAYS call Base first and Continue to add your own results as desired.
    /// Never fail to call base First !
    /// </summary>
    public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
        # region Sample implementation for a POCO thats needs validation

        /* Sample Implementation a sub type POCO might use.
         var validationResult = base.Validate(validationContext).ToList();  

         if (true) // the condition that leads to a validation error
         {
             var memberList = new List<string> { "PropertyName" }; // the name of the offending property
             var error = new ValidationResult("Error text goes here", memberList); // use teh textpool !!! no hardcoded texts
             validationResult.Add(error);
         }

         return validationResult;
       */

        # endregion

        // now back in the base Class.
        var validationResult = new List<ValidationResult>();
        // hand back a list that is empty so errors if any can be added by SUBclasses
        // we can check any Poco that implements a certain interface centrally.  
        var thisIsKeyGuid = this as IFKeyGuid;
        if (thisIsKeyGuid != null) {
            if (thisIsKeyGuid.Id == Guid.Empty) {
                validationResult.Add(new ValidationResult("Id is required", new List<string>() {"Id"}));
            }
        }

        return validationResult;
    }

    /// <summary>
    /// Allows explicit triggering of Validation and returns a TRUE or false answer. Call anytime
    /// </summary>
    /// <returns></returns>
    public virtual bool IsValidInstance() {
        List<ValidationResult> vResults;
        return SelfValidation(out vResults);
    }

    /// <summary>
    /// Calls Self Validation which uses THIS object as the context for validation.
    /// This means you can trigger a validation without first declaring a validation context.
    /// IValidatableObject is effectively called for you. Witch causes "Validate" to be called
    /// </summary>
    /// <returns></returns>
    public IEnumerable<ValidationResult> ValidateInstance() {
        List<ValidationResult> vResults;
        SelfValidation(out vResults);
        return vResults;
    }

    /// <summary>
    /// Although SelfValidation is defined at BaseObject level, this triggers the VALIDATION process on the current Object
    /// see http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.validator.aspx for mroe details
    /// So if a POCO Object has overridden  public virtual IEnumerable of ValidationResult Validate(ValidationContext validationContext) 
    /// then this method will be called.  It should of course call :base.Validate
    /// </summary>
    /// <returns>true or false</returns>
    private bool SelfValidation(out List<ValidationResult> vResults) {
        var vc = new ValidationContext(this, null, null);
        vResults = new List<ValidationResult>();
        var isValid = Validator.TryValidateObject(this, vc, vResults, true);
        return isValid;
    }
}