2012-07-23 90 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