当我们验证一个属性而不遍历它时。它不会更新控件的 Validate.HasError 属性。对此的解决方案是简单的 NotifyPropertyChanged(propertyName)。
NotifyPropertyChanged
当我的属性值更改(在集合中)但没有遍历它时,我正在使用它,它永远不会触发。
所以要么我们应该NotifyPropertyChanged
在属性验证失败时调用,要么我们应该调用NotifyPropertyChanged(null)
通知所有控件来刷新它们的属性。
添加我的 INotifyDataErrorInfo 的完整实现
public class NotifyDataErrorInfoBase<T> : INotifyDataErrorInfo
{
public NotifyDataErrorInfoBase(T model)
{
Model = model;
}
public T Model { get; set; }
protected void SetValue<TValue>(string propertyName, TValue value)
{
typeof(T).GetProperty(propertyName).SetValue(Model, value);
ValidateProperty<TValue>(propertyName);
}
public bool ValidateAllProperties()
{
List<KeyValuePair<string, Type>> lstOfProperties = typeof(T).GetProperties().
Select(u => new KeyValuePair<string, Type>(u.Name, u.PropertyType)).ToList();
foreach (var property in lstOfProperties)
{
Type currentType = property.Value;
if (property.Value == typeof(string))
{
ValidateProperty<string>(property.Key);
}
else if (property.Value == typeof(int))
{
ValidateProperty<int>(property.Key);
}
}
return !HasErrors;
}
private void ValidateProperty<TValue>([CallerMemberName]string propertyName = null)
{
ClearErrors(propertyName);
var validationContext = new ValidationContext(Model) { MemberName = propertyName };
List<ValidationResult> results = new List<ValidationResult>();
var userName = GetValue<TValue>(propertyName);
Validator.TryValidateProperty(userName, validationContext, results);
if (results.Any())
{
foreach (var item in results)
{
AddError(propertyName, item.ErrorMessage);
}
}
}
protected TValue GetValue<TValue>(string propertyName)
{
return (TValue)typeof(T).GetProperty(propertyName).GetValue(Model);
}
Dictionary<string, List<string>> _lstOfErrors = new Dictionary<string, List<string>>();
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
public bool HasErrors => _lstOfErrors.Any();
public IEnumerable GetErrors(string propertyName)
{
return _lstOfErrors.ContainsKey(propertyName) ? _lstOfErrors[propertyName] : null;
}
protected void AddError(string propertyName, string errorMessage)
{
if (!_lstOfErrors.ContainsKey(propertyName))
{
_lstOfErrors[propertyName] = new List<string>();
}
_lstOfErrors[propertyName].Add(errorMessage);
}
protected void OnErrorsChanged(string propertyName)
{
ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
}
protected void ClearErrors(string propertyName)
{
if (_lstOfErrors.ContainsKey(propertyName))
_lstOfErrors.Remove(propertyName);
}
}