Please implement INotifyDataErrorInfo on Screen/PropertyChangedBase (3.0?)
See original GitHub issueThis framework supports many platforms, so it would be great if it would also support the INotifyDataErrorInfo interface to offer custom validation through an async interface which wpf can bind to.
I am willing to contribute if you would consider this to be an option and are open for contributions.
I’ll show what i’ve done so far. It works but apart from the _errorsChanged handler having a strong referenced handler right now
I think a built in solution would be great to have
public class ValidationModelBase : PropertyChangedBase, INotifyDataErrorInfo
{
private Dictionary<string, List<ValidationResult>> _errors = new Dictionary<string, List<ValidationResult>>();
bool INotifyDataErrorInfo.HasErrors => _errors.Keys.Any();
[field:NonSerialized]
private EventHandler<DataErrorsChangedEventArgs> _errorsChanged;
event EventHandler<DataErrorsChangedEventArgs> INotifyDataErrorInfo.ErrorsChanged
{
add { _errorsChanged += value; }
remove { _errorsChanged -= value; }
}
protected void RaiseErrorsChanged(string propertyName)
{
_errorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
}
IEnumerable INotifyDataErrorInfo.GetErrors(string propertyName)
{
if (!_errors.ContainsKey(propertyName))
yield break;
foreach (var result in _errors[propertyName])
{
yield return result;
}
}
private Dictionary<string, CancellationTokenSource> _validateCts = new Dictionary<string, CancellationTokenSource>();
public bool SetValue<T>(ref T backingField, T value, string propertyName)
{
if (object.Equals(backingField, value))
return false;
backingField = value;
var validationDelay = GetValidationDelay(propertyName);
if (validationDelay > 0)
{
CancellationTokenSource source;
if (_validateCts.TryGetValue(propertyName, out source))
{
source.Cancel();
source = new CancellationTokenSource();
_validateCts[propertyName] = source;
}
else
{
source = new CancellationTokenSource();
_validateCts.Add(propertyName, source);
}
Task.Delay(validationDelay, source.Token).ContinueWith(d =>
{
ValidateProperty(value, propertyName);
NotifyOfPropertyChange(propertyName);
}, source.Token);
}
else
{
Task.Run(() =>
{
ValidateProperty(value, propertyName);
NotifyOfPropertyChange(propertyName);
});
}
return true;
}
private void ValidateProperty<T>(T value, string propertyName)
{
var validationResults = ValidationHelper.ValidateProperty(this, value, propertyName);
OnValidateProperty<T>(value, propertyName, validationResults);
if (validationResults.Count > 0)
{
AddErrors(propertyName, validationResults);
RaiseErrorsChanged(propertyName);
}
else
{
ClearErrors(propertyName);
}
}
protected virtual void OnValidateProperty<T>(T value, string propertyName, List<ValidationResult> validationResults)
{
}
protected void AddErrors(string propertyName, List<ValidationResult> validationResults)
{
if (_errors.ContainsKey(propertyName))
{
_errors[propertyName] = validationResults;
}
else
{
_errors.Add(propertyName, validationResults);
}
}
protected void ClearErrors(string propertyName)
{
_errors.Remove(propertyName);
}
protected virtual int GetValidationDelay(string propertyName)
{
var pi = this.GetType().GetProperty(propertyName);
if (pi != null)
{
var delayAttr = pi.GetCustomAttribute<ValidationDelayAttribute>();
if (delayAttr != null)
return delayAttr.Delay;
}
return 0;
}
}
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class ValidationDelayAttribute : Attribute
{
public ValidationDelayAttribute(int delay)
{
Delay = delay;
}
/// <summary>
/// Delay in milliseconds
/// </summary>
public int Delay { get; }
}
Issue Analytics
- State:
- Created 8 years ago
- Comments:7 (7 by maintainers)
Top Results From Across the Web
Using INotifyDataErrorInfo with child objects in model ...
I'm trying to implement INotifyDataErrorInfo and my model has some custom types that require different validation based on their use.
Read more >INotifyDataErrorInfo implementation for several values ...
I have been trying to implement INotifyDataErrorInfo and everything seems to be working except SaveSettings() and especially bool HasErrors.
Read more >How to implement validation before setting a property ...
After validation succeeds, you set the private field and notify the changed property for the UI to be updated according to ViewModel's State....
Read more >INotifyDataErrorInfo in WPF
This article explains multiple validations on the same property in WPF using INotifyDataErrorInfo and Data annotation.
Read more >Implementing INotifyDataErrorInfo (WPF) : r/csharp
Personally I am a fan of form validation on user click and not on property changed. I hope I described my ask clearly...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
ok i’ve browsed through the code of ConventionManager.cs and i guess i can see now how to provide a plugin based on that. I’m busy with other things right now but i’d probably work on it on the weekend and nudge you to have a look if i did it as you would have imagined this to be done (If that’s ok with you.) ?
No worries.