Currently I'm developing .net 4.5 wpf MVVM application with validation system handled by INotifyDataErrorInfo. At some point in application I have to check if there are any validation errors, currently it's done like this:
public class RootViewModel : BindableBase
{
//class code
if (designInformation.Technology == Technology.CVT)
{
if (designInformation.HasErrors) return;
if (InfoInputViewModel.TrafoProperties.HasErrors) return;
if (InfoInputViewModel.CapacitorVoltageTransformerViewModel.CapacitorVoltageDivider.HasErrors) return;
if (InfoInputViewModel.CapacitorVoltageTransformerViewModel.IntermediateVoltageTransformer.HasErrors) return;
if (SpecialDesignViewModel.SpecialDesignInformation.HasErrors) return;
foreach (var item in InfoInputViewModel.SecondaryWindings.WindingsCollection)
{
if (item.HasErrors) return;
}
performCalculationsCVT();
}
}
And I'm looking for a way to simplify this code by getting all errors from model at once, but don't know where to start with this problem.
Bellow is implementation of INotifyDataErrorInfo interface i use.
public class ValidableBase : BindableBase, INotifyDataErrorInfo
{
protected readonly Dictionary<string, ICollection<string>>
_validationErrors = new Dictionary<string, ICollection<string>>();
#region INotifyDataErrorInfo Implementation
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
protected void RaiseErrorsChanged(string propertyName)
{
if (ErrorsChanged != null)
ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
}
public IEnumerable GetErrors(string propertyName)
{
if (string.IsNullOrEmpty(propertyName) || !_validationErrors.ContainsKey(propertyName))
return null;
return _validationErrors[propertyName];
}
public bool HasErrors
{
get { return _validationErrors.Count > 0; }
}
public void AddError(string propertyName, string message)
{
if (_validationErrors.ContainsKey(propertyName))
{
string value = _validationErrors[propertyName].First();
value += Environment.NewLine;
value += message;
_validationErrors[propertyName] = new List<string> { value };
}
else
_validationErrors[propertyName] = new List<string> { message };
RaiseErrorsChanged(propertyName);
}
public void RemoveError(string propertyName)
{
_validationErrors.Remove(propertyName);
RaiseErrorsChanged(propertyName);
}
[XmlIgnore]
public Dictionary<string, ICollection<string>> ValidationErrors
{
get { return this._validationErrors; }
}
#endregion
}
}
Obviously, the base class has no idea what properties a particular child class has, let alone if they implement INDEI. You'll have to write the logic to do this. There are many ways you can accomplish this.
For me, I'd add an abstract method to the base class thusly
Then change HasErrors to call HasErrors recursively on the results of the above call
An example implementation of GetValidableProperties might be
Lastly, I'd rename Validable to Validatable, which is the correct (english) spelling. If I were Spanish or French, I'd probably skip that last step.