Get check results

I am using EntLib 6 validator with WPF integration. Simple property in my virtual machine:

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

      

And the corresponding binding to the text block:

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

      

If more than three characters are entered in the text box, the value is rejected and the last valid one is retained. The TextBox is highlighted in red and the corresponding message is displayed as a ToolTip.

Inside the VM, I would like to check if there are any validation errors, but since the value is rejected in the view, everything seems to be fine. So how do I determine if there was a validation error?

WARNING: VAB does NOT use the IDataErrorInfo interface!

+3


source to share


1 answer


I don't know what a simple and straightforward way to get validation results from your ViewModel when you use WPF's built-in validation APIs. However, while VAB cannot use IDataErrorInfo

out of the box, you can add the integration quite easily and you only need to change the base view model class. You can start with something like this:

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;
}

      



This view model performs validation using the authentication block APIs whenever the property changes and reports the results through IDataErrorInfo

. You will need to set ValidatesOnDataErrors

in ads Binding

for this to work.

0


source







All Articles