How to properly implement INotifyDataErrorInfo?

2020-07-17 07:38发布

问题:

I'm a little confused by MSDN example.

It's not clear how to treat and set entity realted errors.

Code in example:

public System.Collections.IEnumerable GetErrors(string propertyName)
{
    if (String.IsNullOrEmpty(propertyName) || 
        !errors.ContainsKey(propertyName)) return null;
    return errors[propertyName];
}

but documentation for GetErrors() states:

propertyName - The name of the property to retrieve validation errors for; or null or Empty, to retrieve entity-level errors.

Another example suggests just returning _errors.Values of the dictionary. And this is just all properties errors but again not entity errors.

回答1:

As per the "Remarks" section from the documentation: MSDN: INotifyDataErrorInfo Interface

This interface enables data entity classes to implement custom validation rules and expose validation results asynchronously. This interface also supports custom error objects, multiple errors per property, cross-property errors, and entity-level errors. Cross-property errors are errors that affect multiple properties. You can associate these errors with one or all of the affected properties, or you can treat them as entity-level errors. Entity-level errors are errors that either affect multiple properties or affect the entire entity without affecting a particular property.

I might suggest that the implementation of GetErrors is highly dependent upon your error handling scheme. If, for instance, you do not intend to support Entity-Level errors, then your example code is sufficient. If, however, you do need to support Entity-Level errors, then you may handle the IsNullOrEmpty condition separately:

Public IEnumerable GetErrors(String propertyName)
{
    if (String.IsNullOrEmpty(propertyName))
        return entity_errors;
    if (!property_errors.ContainsKey(propertyName))
        return null;
    return property_errors[propertyName];
}


回答2:

As I haven't found an proper answer here my solution, all validation errors are returned when the value is null or empty:

private ConcurrentDictionary<string, List<ValidationResult>> modelErrors = new ConcurrentDictionary<string, List<ValidationResult>>();

public bool HasErrors { get => modelErrors.Any(); }

public IEnumerable GetErrors(string propertyName)
{
    if (string.IsNullOrEmpty(propertyName))
    {
        return modelErrors.Values.SelectMany(x => x);   // return all errors
    }
    modelErrors.TryGetValue(propertyName, out var propertyErrors);
    return propertyErrors;
}