2014-11-21 70 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