/// <summary> /// Is called by the indexer to collect all errors and not only the one for a special field. /// </summary> /// <remarks> /// Because <see cref="HasErrors" /> depends on the <see cref="Errors" /> dictionary this /// ensures that controls like buttons can switch their state accordingly. /// </remarks> private void CollectErrors() { Errors.Clear(); PropertyInfos.ForEach( prop => { var currentValue = prop.GetValue(this); var requiredAttr = prop.GetCustomAttribute <RequiredAttribute>(); var maxLenAttr = prop.GetCustomAttribute <MaxLengthAttribute>(); if (requiredAttr != null) { if (string.IsNullOrEmpty(currentValue?.ToString() ?? string.Empty)) { Errors.Add(prop.Name, requiredAttr.ErrorMessage); } } if (maxLenAttr != null) { if ((currentValue?.ToString() ?? string.Empty).Length > maxLenAttr.Length) { Errors.Add(prop.Name, maxLenAttr.ErrorMessage); } } // TODO further attributes }); // we have to this because the Dictionary does not implement INotifyPropertyChanged OnPropertyChanged(nameof(HasErrors)); OnPropertyChanged(nameof(IsOk)); // commands do not recognize property changes automatically OnErrorsCollected(); }
/// <summary> /// Is called by the indexer to collect all errors and not only the one for a special field. /// </summary> /// <remarks> /// Because <see cref="HasErrors" /> depends on the <see cref="Errors" /> dictionary this /// ensures that controls like buttons can switch their state accordingly. /// </remarks> private void CollectErrors() { Errors.Clear(); PropertyInfos.ForEach( prop => { //Validate generically var errors = new List <string>(); var isValid = TryValidateProperty(prop, errors); if (!isValid) { Errors.Add(prop.Name, errors.FirstOrDefault()); } }); // we have to this because the Dictionary does not implement INotifyPropertyChanged OnPropertyChanged(nameof(HasErrors)); OnPropertyChanged(nameof(IsOk)); // commands do not recognize property changes automatically OnErrorsCollected(); }