2014-11-21 63 views
3

我正在使用WPF集成的EntLib 6驗證塊。 簡單的屬性在我的VM:獲取驗證結果

[StringLengthValidator(3, MessageTemplate = "Shorten me!")] 
    public String SomeText 
    { 
     get { return _someText; } 
     set 
     { 
      _someText = value; 
      OnPropertyChanged("SomeText"); 
     } 
    } 

而且相應的綁定到一個文本框:

<TextBox ToolTip="{Binding (Validation.Errors).CurrentItem.ErrorContent, RelativeSource={x:Static RelativeSource.Self}}" 
     Text="{Binding SomeText, UpdateSourceTrigger=PropertyChanged}" 
     vab:Validate.BindingForProperty="Text"/> 

如果輸入多於三個字符到文本框,值被拒絕,最後一個有效的一個是存儲。文本框以紅色突出顯示,相應的消息顯示爲工具提示。

在虛擬機內我想檢查是否有任何驗證錯誤 - 但由於該值在視圖中被拒絕,一切似乎都沒有問題。那麼如何確定是否存在驗證錯誤?

注意: VAB不使用IDataErrorInfo接口!

回答

0

當您使用WPF的內置驗證API時,我不知道從視圖模型獲取驗證結果的乾淨而直接的方法。但是,儘管VAB可能不會使用IDataErrorInfo,但您可以相當容易地添加集成,並且只需修改基本視圖模型類。你可以像這樣的東西開始:

public class ValidatingModel : INotifyPropertyChanged, IDataErrorInfo 
{ 
    private readonly Dictionary<string, PropertyInfo> _properties; 
    private readonly Dictionary<string, Validator> _propertyValidators; 
    private readonly Dictionary<string, ValidationResults> _validationResults; 

    private string _compositeMessage; 

    public ValidatingModel() 
    { 
     _properties = new Dictionary<string, PropertyInfo>(); 
     _propertyValidators = new Dictionary<string, Validator>(); 
     _validationResults = new Dictionary<string, ValidationResults>(); 

     PopulateValidators(); 
    } 

    private void PopulateValidators() 
    { 
     var properties = GetType().GetProperties(
      BindingFlags.Instance | 
      BindingFlags.Public); 

     foreach (var property in properties) 
     { 
      var attributes = property.GetCustomAttributes(
       typeof(ValueValidatorAttribute), 
       false); 

      if (attributes.Length == 0 || _properties.ContainsKey(property.Name)) 
       continue; 

      _properties[property.Name] = property; 

      _propertyValidators[property.Name] = 
       PropertyValidationFactory.GetPropertyValidatorFromAttributes(
        property.PropertyType, 
        property, 
        string.Empty, 
        new MemberAccessValidatorBuilderFactory()); 
     } 
    } 

    protected IEnumerable<ValidationResult> GetValidationResults() 
    { 
     foreach (var results in _validationResults.Values) 
     { 
      foreach (var result in results) 
       yield return result; 
     } 
    } 

    protected IEnumerable<ValidationResult> GetValidationResults(string property) 
    { 
     if (_propertyValidators.ContainsKey(property)) 
     { 
      ValidationResults results; 

      if (!_validationResults.TryGetValue(property, out results)) 
       Validate(property); 

      if (!_validationResults.TryGetValue(property, out results)) 
       yield break; 

      foreach (var result in results) 
       yield return result; 
     } 
    } 

    protected void Validate(string propertyName) 
    { 
     if (_propertyValidators.ContainsKey(propertyName)) 
     { 
      _compositeMessage = null; 
      _validationResults[propertyName] = Validation.Validate(this); 
     } 
    } 

    string IDataErrorInfo.this[string columnName] 
    { 
     get 
     { 
      ValidationResults results; 

      if (!_validationResults.TryGetValue(columnName, out results)) 
       Validate(columnName); 

      if (_validationResults.TryGetValue(columnName, out results)) 
       return CombineMessages(results); 

      return null; 
     } 
    } 

    string IDataErrorInfo.Error 
    { 
     get 
     { 
      if (_compositeMessage != null) 
       return _compositeMessage; 

      foreach (var validator in _propertyValidators) 
      { 
       if (_validationResults.ContainsKey(validator.Key)) 
        continue; 

       _validationResults[validator.Key] = ValidateProperty(
        validator.Value, 
        _properties[validator.Key]); 
      } 

      _compositeMessage = CombineMessages(
       _validationResults.SelectMany(r => r.Value)); 

      return _compositeMessage; 
     } 
    } 

    private ValidationResults ValidateProperty(
     Validator validator, 
     PropertyInfo propertyInfo) 
    { 
     return validator.Validate(propertyInfo.GetValue(this, null)); 
    } 

    private static string CombineMessages(IEnumerable<ValidationResult> results) 
    { 
     return results.Aggregate(
      new StringBuilder(), 
      (sb, p) => (sb.Length > 0 ? sb.AppendLine() : sb).Append(p.Message), 
      sb => sb.ToString()); 
    } 

    protected void OnPropertyChanged(string propertyName) 
    { 
     Validate(propertyName); 

     var handler = this.PropertyChanged; 
     if (handler != null) 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
} 

這個視圖模型使用驗證應用程序塊的API進行驗證,只要通過IDataErrorInfo屬性的變化,並報告結果。您需要在Binding聲明上設置ValidatesOnDataErrors才能使其工作。

+0

vab防止綁定將無效值傳遞給VM - 無論啓用ValidatesOnDataErrors – Jaster 2014-12-01 09:23:15