2011-11-16 73 views
1

我試圖找到一個簡單的方法來驗證通過ViewModels的集合,使用IDataErrorInfo接口。IDataErrorInfo/WPF綁定 - 通過許多ViewModel驗證

我有一個ListBox,它綁定到ViewModels的ObservableCollection。

  • 1類 「DataView<VMUser>」 與ObservableCollection<VMUser>
  • 1 ViewModel類 「VMUser

如果我實施IDataErrorInfo的進入我的ViewModel,我可以驗證,例如,如果年齡> 21等在...但我不能驗證是否沒有其他用戶使用相同的電子郵件爲例,因爲ViewModels彼此不知道任何東西。

我沒有找到一種方法來強制我的VMUser-DataTemplate中的綁定使用DataView類的IDataErrorInfo。 (沒有點擊確定按鈕...)

回答

2

對於基於業務規則的驗證,我通常公開一個驗證委託,我的ViewModel可以設置。

例如,包含您的收藏視圖模型可能是這樣的:

public ParentViewModel() 
{ 
    foreach(var user in UserCollection) 
     user.AddValidationErrorDelegate(ValidateUser); 
} 

private string ValidateUser(object sender, string propertyName) 
{ 
    if (propertyName == "Email") 
    { 
     var user = (UserVM)sender; 

     if (UserCollection.Count(p => p.Email== user.Email) > 1) 
      return "Another user already has this Email Address"; 
    } 
    return null; 
} 

的想法是,你Model應該只包含原始數據,因此它應該只驗證原始數據。這可以包括驗證最大長度,必填字段和允許的字符等內容。包含業務規則的業務邏輯應在ViewModel中進行驗證,並允許這樣做。

UserVM類實際執行的我IDataErrorInfo應該是這樣的:

#region IDataErrorInfo & Validation Members 

/// <summary> 
/// List of Property Names that should be validated 
/// </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) 
{ 
    // If user specified properties to validate, check to see if this one exists in the list 
    if (ValidatedProperties.IndexOf(propertyName) < 0) 
    { 
     //Debug.Fail("Unexpected property being validated on " + this.GetType().ToString() + ": " + propertyName); 
     return null; 
    } 

    string s = null; 

    // If user specified a Validation method to use, Validate property 
    if (_validationDelegates.Count > 0) 
    { 
     foreach (ValidationErrorDelegate 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 
+0

我喜歡@Rachel了這裏的方法。我一直在使用IDataErrorInfo.this []從模型中暴露範圍錯誤,但只有在用戶單擊確定後才能運行業務規則檢查。在用戶完成填寫表單的其餘部分並單擊確定之前,能夠使用像這樣的方法將業務規則錯誤暴露給UI *是很好的。 – Kendrick

+0

這就是我正在尋找的!填寫表單時,通過IDataErrorInfo執行「更高級別」檢查的一種非常好且簡單的方法。 :) – Christian