Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.ComponentModel.DataAnnotations;
- using System.Linq;
- namespace TM
- {
- /// <summary>
- /// Supports validation according to <see cref="INotifyDataErrorInfo"/> via validation attributes
- /// (<see cref="ValidationAttribute"/>) decorating the properties of validated class.
- /// Validated class should create an instance of <see cref="ValidatorComponent"/>, passing itself as a parameter.
- /// <see cref="HasErrors"/> and <see cref="GetErrors(string)"/> should be delegated
- /// to <see cref="ValidatorComponent"/>, while <see cref="ErrorsChanged"/> should be propagated upwards.
- /// </summary>
- public class ValidatorComponent
- {
- /// <summary>
- /// Validation errors grouped by invalid member names
- /// </summary>
- private Dictionary<string, List<ValidationResult>> _validationErrors
- = new Dictionary<string, List<ValidationResult>>();
- /// <summary>
- /// Reference to the validated object
- /// </summary>
- public INotifyPropertyChanged ValidatedInstance { get; private set; }
- public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
- /// <summary>
- /// Creates new instance of <see cref="ValidatorComponent"/> observing a given <paramref name="validatedInstance"/>.
- /// </summary>
- /// <param name="validatedInstance">reference to the validated object</param>
- public ValidatorComponent(INotifyPropertyChanged validatedInstance)
- {
- ValidatedInstance = validatedInstance;
- ValidatedInstance.PropertyChanged +=
- (source, propertyName) => PerformValidation();
- PerformValidation();
- }
- public bool HasErrors
- {
- get { return _validationErrors.Values.Any(item => item != null && item.Count > 0); }
- }
- public System.Collections.IEnumerable GetErrors(string propertyName)
- {
- if (string.IsNullOrEmpty(propertyName))
- return Enumerable.Empty<ValidationResult>();
- List<ValidationResult> errors = null;
- if (_validationErrors.TryGetValue(propertyName, out errors))
- return errors;
- return Enumerable.Empty<ValidationResult>();
- }
- /// <summary>
- /// Validates the <see cref="ValidatedInstance"/>, updates errors collection
- /// and notifies listeners via <see cref="ErrorsChanged"/> event.
- /// </summary>
- public void PerformValidation()
- {
- var oldMembers = _validationErrors.Values.SelectMany(list => list.SelectMany(x => x.MemberNames)).Distinct().ToList();
- _validationErrors.Clear();
- var context = new ValidationContext(ValidatedInstance);
- List<ValidationResult> errors = new List<ValidationResult>();
- var result = Validator.TryValidateObject(ValidatedInstance, context, errors, true);
- foreach (var member in oldMembers)
- ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(member));
- if (result == true)
- return;
- foreach (var error in errors)
- {
- foreach (var member in error.MemberNames)
- {
- if (_validationErrors.ContainsKey(member) == false)
- _validationErrors[member] = new List<ValidationResult>();
- if (_validationErrors[member].Any(err => err.ErrorMessage == error.ErrorMessage))
- continue;
- _validationErrors[member].Add(error);
- }
- }
- ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(string.Empty));
- var members = errors.SelectMany(x => x.MemberNames).Distinct();
- foreach (var member in members)
- ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(member));
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement