Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The option I went with was to implement IDataErrorInfo explicitly in a base class which is extended by all ViewModels and Entities. This seems the best compromise to get things ticking over with WPF, and at least keeps the implementation of IDataErrorInfo hidden to callers so they at least appear clean. I expose a protected ValidateProperty which can be overridden if necessary in subclasses for any custom behaviour (such as for Password/PasswordConfirmation scenario).</p> <pre><code>public abstract class DataErrorInfo : IDataErrorInfo { string IDataErrorInfo.Error { get { return null; } } string IDataErrorInfo.this[string columnName] { get { return ValidateProperty(columnName); } } protected virtual string ValidateProperty(string columnName) { // get cached property accessors var propertyGetters = GetPropertyGetterLookups(GetType()); if (propertyGetters.ContainsKey(columnName)) { // read value of given property var value = propertyGetters[columnName](this); // run validation var results = new List&lt;ValidationResult&gt;(); var vc = new ValidationContext(this, null, null) { MemberName = columnName }; Validator.TryValidateProperty(value, vc, results); // transpose results var errors = Array.ConvertAll(results.ToArray(), o =&gt; o.ErrorMessage); return string.Join(Environment.NewLine, errors); } return string.Empty; } private static readonly Dictionary&lt;string, object&gt; PropertyLookupCache = new Dictionary&lt;string, object&gt;(); private static Dictionary&lt;string, Func&lt;object, object&gt;&gt; GetPropertyGetterLookups(Type objType) { var key = objType.FullName ?? ""; if (!PropertyLookupCache.ContainsKey(key)) { var o = objType.GetProperties() .Where(p =&gt; GetValidations(p).Length != 0) .ToDictionary(p =&gt; p.Name, CreatePropertyGetter); PropertyLookupCache[key] = o; return o; } return (Dictionary&lt;string, Func&lt;object, object&gt;&gt;)PropertyLookupCache[key]; } private static Func&lt;object, object&gt; CreatePropertyGetter(PropertyInfo propertyInfo) { var instanceParameter = Expression.Parameter(typeof(object), "instance"); var expression = Expression.Lambda&lt;Func&lt;object, object&gt;&gt;( Expression.ConvertChecked( Expression.MakeMemberAccess( Expression.ConvertChecked(instanceParameter, propertyInfo.DeclaringType), propertyInfo), typeof(object)), instanceParameter); var compiledExpression = expression.Compile(); return compiledExpression; } private static ValidationAttribute[] GetValidations(PropertyInfo property) { return (ValidationAttribute[])property.GetCustomAttributes(typeof(ValidationAttribute), true); } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload