2014-11-21 4 views
3

Я использую блок проверки EntLib 6 с интеграцией WPF. Простой недвижимости в моей виртуальной машине:Получить результаты проверки

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

И соответствующий Binding к TextBox:

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

Если ввести более трех символов в TextBox значение отвергается и последний действующий один сохраняются. TextBox выделяется красным цветом, и соответствующее сообщение отображается как ToolTip.

Внутри виртуальной машины я хотел бы проверить, есть ли какие-либо ошибки проверки - но поскольку значение отклонено в представлении, все кажется прекрасным. Итак, как мне определить, была ли ошибка проверки?

ВНИМАНИЕ: VAB НЕ использовать IDataErrorInfo интерфейс!

ответ

0

Я не знаю, какой простой и простой способ получить результаты валидации из вашей модели просмотра, когда вы используете встроенные API проверки WPF. Однако, хотя 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-интерфейсов Validation Application Block, когда свойство изменяется, и сообщает результаты через IDataErrorInfo. Вам нужно будет установить ValidatesOnDataErrors на ваши объявления Binding, чтобы это сработало.

+0

vab запрещает привязку передавать недействительные значения виртуальной машине - независимо от того, включена ли функция ValidatesOnDataErrors – Jaster