refactor validations further for more flexible interface.
MODIFY
WalletWasabi.Gui/Converters/ErrorDescriptorToBorderColorConverter.cs
WalletWasabi.Gui/Converters/ErrorDescriptorToBorderColorConverter.cs
@@ -32,7 +32,7 @@ namespace WalletWasabi.Gui.Converters
private SolidColorBrush GetColorFromDescriptors(ErrorDescriptors descriptors)
{
- if (!descriptors.HasErrors)
+ if (!descriptors.Any())
{
return null;
}

MODIFY
WalletWasabi.Gui/Tabs/SettingsViewModel.cs
WalletWasabi.Gui/Tabs/SettingsViewModel.cs
@@ -330,9 +330,10 @@ namespace WalletWasabi.Gui.Tabs
return;
}
+ // TODO test if this call is needed.. it shouldnt be.
Validate();
- if (HasErrors)
+ if (Validations.Any)
{
return;
}

MODIFY
WalletWasabi.Gui/Tabs/WalletManager/GenerateWallets/GenerateWalletViewModel.cs
WalletWasabi.Gui/Tabs/WalletManager/GenerateWallets/GenerateWalletViewModel.cs
@@ -26,7 +26,7 @@ namespace WalletWasabi.Gui.Tabs.WalletManager.GenerateWallets
this.ValidateProperty(x => x.Password, ValidatePassword);
- NextCommand = ReactiveCommand.Create(DoNextCommand, this.WhenAnyValue(x => x.HasErrors).Select(x => !x));
+ NextCommand = ReactiveCommand.Create(DoNextCommand, this.WhenAnyValue(x => x.Validations.Any).Select(x => !x));
NextCommand.ThrownExceptions
.ObserveOn(RxApp.TaskpoolScheduler)

ADD
WalletWasabi.Gui/Validation/IValidations.cs
+using System.Collections.Generic;
+
+namespace WalletWasabi.Gui.Validation
+{
+ public interface IValidations
+ {
+ bool Any { get; }
+
+ bool AnyErrors { get; }
+
+ bool AnyWarnings { get; }
+
+ bool AnyInfos { get; }
+
+ IEnumerable<string> Infos { get; }
+
+ IEnumerable<string> Warnings { get; }
+
+ IEnumerable<string> Errors { get; }
+ }
+}

ADD
WalletWasabi.Gui/Validation/Validations.cs
+using ReactiveUI;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using WalletWasabi.Models;
+
+namespace WalletWasabi.Gui.Validation
+{
+ public class Validations : ReactiveObject, IRegisterValidationMethod, IValidations
+ {
+ private Dictionary<string, ErrorDescriptors> _errorsByPropertyName;
+ private Dictionary<string, ValidateMethod> _validationMethods;
+
+ public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
+
+ public Validations()
+ {
+ _errorsByPropertyName = new Dictionary<string, ErrorDescriptors>();
+ _validationMethods = new Dictionary<string, ValidateMethod>();
+ }
+
+ public void Validate()
+ {
+ foreach (var propertyName in _validationMethods.Keys)
+ {
+ ValidateProperty(propertyName);
+ }
+ }
+
+ public void ValidateProperty(string propertyName)
+ {
+ if (_validationMethods.ContainsKey(propertyName))
+ {
+ ClearErrors(propertyName);
+
+ var del = _validationMethods[propertyName];
+
+ var method = del as ValidateMethod;
+
+ method(_errorsByPropertyName[propertyName]);
+
+ OnErrorsChanged(propertyName);
+ }
+ }
+
+ void IRegisterValidationMethod.RegisterValidationMethod(string propertyName, ValidateMethod validateMethod)
+ {
+ if (string.IsNullOrWhiteSpace(propertyName))
+ {
+ throw new ArgumentException("PropertyName must be valid.", nameof(propertyName));
+ }
+
+ _validationMethods[propertyName] = validateMethod;
+ _errorsByPropertyName[propertyName] = ErrorDescriptors.Create();
+ }
+
+ public IEnumerable GetErrors(string propertyName)
+ {
+ return _errorsByPropertyName.ContainsKey(propertyName) && _errorsByPropertyName[propertyName].Any()
+ ? _errorsByPropertyName[propertyName]
+ : ErrorDescriptors.Empty;
+ }
+
+ private void ClearErrors(string propertyName)
+ {
+ if (_errorsByPropertyName.ContainsKey(propertyName))
+ {
+ _errorsByPropertyName[propertyName].Clear();
+
+ OnErrorsChanged(propertyName);
+ }
+ }
+
+ private void OnErrorsChanged(string propertyName)
+ {
+ ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
+
+ this.RaisePropertyChanged(nameof(Any));
+ this.RaisePropertyChanged(nameof(AnyErrors));
+ this.RaisePropertyChanged(nameof(AnyWarnings));
+ this.RaisePropertyChanged(nameof(AnyInfos));
+ }
+
+ public bool Any => _errorsByPropertyName.Where(x => x.Value.Any()).Any();
+
+ public bool AnyErrors => _errorsByPropertyName.Where(x => x.Value.Any(x => x.Severity == ErrorSeverity.Error)).Any();
+
+ public bool AnyWarnings => _errorsByPropertyName.Where(x => x.Value.Any(x => x.Severity == ErrorSeverity.Warning)).Any();
+
+ public bool AnyInfos => _errorsByPropertyName.Where(x => x.Value.Any(x => x.Severity == ErrorSeverity.Info)).Any();
+
+ IEnumerable<string> IValidations.Infos => throw new NotImplementedException();
+
+ IEnumerable<string> IValidations.Warnings => throw new NotImplementedException();
+
+ IEnumerable<string> IValidations.Errors => throw new NotImplementedException();
+ }
+}

MODIFY
WalletWasabi.Gui/ViewModels/ViewModelBase.cs
WalletWasabi.Gui/ViewModels/ViewModelBase.cs
using ReactiveUI;
using System;
using System.Collections;
-using System.Collections.Generic;
using System.ComponentModel;
-using System.Linq;
-using System.Reflection;
using WalletWasabi.Gui.Validation;
-using WalletWasabi.Models;
namespace WalletWasabi.Gui.ViewModels
{
public class ViewModelBase : ReactiveObject, INotifyDataErrorInfo, IRegisterValidationMethod
{
- private Dictionary<string, ErrorDescriptors> _errorsByPropertyName;
- private Dictionary<string, ValidateMethod> _validationMethods;
+ private Validations _validations;
+
+ public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
public ViewModelBase()
{
- _errorsByPropertyName = new Dictionary<string, ErrorDescriptors>();
- _validationMethods = new Dictionary<string, ValidateMethod>();
-
+ _validations = new Validations();
+ _validations.ErrorsChanged += OnValidations_ErrorsChanged;
PropertyChanged += ViewModelBase_PropertyChanged;
}
- public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
-
- public bool HasErrors => _errorsByPropertyName.Where(x => x.Value.HasErrors).Any();
+ protected IValidations Validations => _validations;
- void IRegisterValidationMethod.RegisterValidationMethod(string propertyName, ValidateMethod validateMethod)
- {
- if (string.IsNullOrWhiteSpace(propertyName))
+ protected void Validate()
{
- throw new ArgumentException("PropertyName must be valid.", nameof(propertyName));
+ _validations.Validate();
}
- _validationMethods[propertyName] = validateMethod;
- _errorsByPropertyName[propertyName] = ErrorDescriptors.Create();
- }
-
- protected void Validate()
- {
- foreach (var propertyName in _validationMethods.Keys)
+ private void OnValidations_ErrorsChanged(object sender, DataErrorsChangedEventArgs e)
{
- DoValidateProperty(propertyName);
- }
+ ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(e.PropertyName));
}
private void ViewModelBase_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (string.IsNullOrWhiteSpace(e.PropertyName))
{
- Validate();
+ _validations.Validate();
}
else
{
- DoValidateProperty(e.PropertyName);
- }
- }
-
- private void DoValidateProperty(string propertyName)
- {
- if (_validationMethods.ContainsKey(propertyName))
- {
- ClearErrors(propertyName);
-
- var del = _validationMethods[propertyName];
-
- var method = del as ValidateMethod;
-
- method(_errorsByPropertyName[propertyName]);
-
- OnErrorsChanged(propertyName);
-
- this.RaisePropertyChanged(nameof(HasErrors));
+ _validations.ValidateProperty(e.PropertyName);
}
}
- public IEnumerable GetErrors(string propertyName)
- {
- return _errorsByPropertyName.ContainsKey(propertyName) && _errorsByPropertyName[propertyName].HasErrors
- ? _errorsByPropertyName[propertyName]
- : ErrorDescriptors.Empty;
- }
+ bool INotifyDataErrorInfo.HasErrors => (_validations as IValidations).Any;
- private void ClearErrors(string propertyName)
+ IEnumerable INotifyDataErrorInfo.GetErrors(string propertyName)
{
- if (_errorsByPropertyName.ContainsKey(propertyName))
- {
- _errorsByPropertyName[propertyName].Clear();
-
- OnErrorsChanged(propertyName);
-
- this.RaisePropertyChanged(nameof(HasErrors));
- }
+ return _validations.GetErrors(propertyName);
}
- private void OnErrorsChanged(string propertyName)
+ void IRegisterValidationMethod.RegisterValidationMethod(string propertyName, ValidateMethod validateMethod)
{
- ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
+ ((IRegisterValidationMethod)_validations).RegisterValidationMethod(propertyName, validateMethod);
}
}
}

MODIFY
WalletWasabi/Models/ErrorDescriptors.cs
WalletWasabi/Models/ErrorDescriptors.cs
@@ -10,8 +10,6 @@ namespace WalletWasabi.Models
{
}
- public bool HasErrors => Count > 0;
-
public static ErrorDescriptors Create()
{
return new ErrorDescriptors();

refactor validations further for more flexible interface.