2012-07-23 107 views
1

我正在使用实体框架4.3使用WPF和MVVM的项目,我想知道如何执行实现IDataErrorInfo接口的业务逻辑验证。实体框架和IDataErrorInfo业务逻辑验证

我所有的模型(POCO类),以执行原始验证,如最大长度,非负数,等正在实施它...

但对于经营业务逻辑验证,如防止重复记录?

想象我有一个材料“参考”,它必须是独特的文本框,定义人喜欢:

<TextBox Text="{Binding Material.Reference, ValidatesOnDataErrors=True, NotifyOnValidationError=true, 
           UpdateSourceTrigger=PropertyChanged}"> 

该模型将成功验证的参考的长度,但如果已经有一个材料,我的视图模型的材料observablecollection,我应该如何从我的ViewModel通知用户这一事实,但利用IDataErrorInfo消息?

回答

2

我已经从我的模型暴露验证委托做到了这一点,在过去,我的ViewModels可以挂接到额外的业务逻辑验证

最终的结果结束了看起来像这样:

public class MyViewModel 
{ 
    // Keeping these generic to reduce code here, but they 
    // should be full properties with PropertyChange notification 
    public ObservableCollection<MyModel> MyCollection { get; set; } 
    public MyModel SelectedModel { get; set; } 

    public MyViewModel() 
    { 
     MyCollection = DAL.GetAllModels(); 

     // Add the validation delegate to each object 
     foreach(var model in MyCollection) 
      model.AddValidationErrorDelegate(ValidateModel); 
    } 

    // Validation Delegate to verify the object's name is unique 
    private string ValidateObject(object sender, string propertyName) 
    { 
     if (propertyName == "Name") 
     { 
      var obj = (MyModel)sender; 
      var existingCount = MyCollection.Count(p => 
       p.Name == obj.Name && p.Id != obj.Id); 

      if (existingCount > 0) 
       return "This name has already been taken"; 
     } 
     return null; 
    } 
} 

我的大多数模型都从泛型基类继承而来,其中包含此验证委托。下面是从基类,从我的博客文章中所采取的相关代码上Validating Business Rules in MVVM

#region IDataErrorInfo & Validation Members 

/// <summary> 
/// List of Property Names that should be validated. 
/// Usually populated by the Model's Constructor 
/// </summary> 
protected List<string> ValidatedProperties = new List<string>(); 

#region Validation Delegate 

public delegate string ValidationErrorDelegate(
    object sender, string propertyName); 

private List<ValidationErrorDelegate> _validationDelegates = new List<ValidationErrorDelegate>(); 

public void AddValidationErrorDelegate(
    ValidationErrorDelegate func) 
{ 
    _validationDelegates.Add(func); 
} 

#endregion // Validation Delegate 

#region IDataErrorInfo for binding errors 

string IDataErrorInfo.Error { get { return null; } } 

string IDataErrorInfo.this[string propertyName] 
{ 
    get { return this.GetValidationError(propertyName); } 
} 

public string GetValidationError(string propertyName) 
{ 
    // Check to see if this property has any validation 
    if (ValidatedProperties.IndexOf(propertyName) >= 0) 
    { 
     string s = null; 

     foreach (var func in _validationDelegates) 
     { 
      s = func(this, propertyName); 
      if (s != null) 
       return s; 
     } 
    } 

    return s; 
} 

#endregion // IDataErrorInfo for binding errors 

#region IsValid Property 

public bool IsValid 
{ 
    get 
    { 
     return (GetValidationError() == null); 
    } 
} 

public string GetValidationError() 
{ 
    string error = null; 

    if (ValidatedProperties != null) 
    { 
     foreach (string s in ValidatedProperties) 
     { 
      error = GetValidationError(s); 
      if (error != null) 
       return error; 
     } 
    } 

    return error; 
} 

#endregion // IsValid Property 

#endregion // IDataErrorInfo & Validation Members 

这使我能够保持基本的数据验证在我的模型,我的ViewModels可以将他们想要的任何定制的业务逻辑验证型号也是如此。

+0

谢谢,我已经离开了办公室,但明天我会试试这个。 – 2012-07-23 18:23:15

+0

它很好用!只是为了让你知道,你的代码包含如下小错误:列表类型没有定义,s没有定义,并且在ValidatedProperties.IndexOf(propertyName)0中缺少> =运算符。 – 2012-07-24 10:13:43

+0

@EduardoBrites谢谢,我遇到了问题当我将代码复制到它时,wordpress会删除一些特殊字符,所以我肯定会在本周末修复这个问题:) – Rachel 2012-07-24 11:55:20