caloggins
7/22/2014 - 6:03 PM

Usese MVVM Light

Usese MVVM Light

namespace MonitorMessageGenerator.Code
{
    using System;
    using System.Collections;
    using System.Collections.Concurrent;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using System.Threading.Tasks;

    using GalaSoft.MvvmLight;

    public abstract class MyViewModelBase : ViewModelBase, INotifyDataErrorInfo
    {
        private readonly object @lock = new object();
        private readonly ConcurrentDictionary<string, List<string>> errors = new ConcurrentDictionary<string, List<string>>();
        
        protected virtual void OnPropertyChanged([CallerMemberName] string name = null)
        {

            var e = PropertyChangedHandler;
            if (e != null)
                e(this, new PropertyChangedEventArgs(name));

            ValidateAsync();
        }

        protected async void ValidateAsync()
        {
            await Task.Run(() => Validate());
        }

        public virtual void Validate()
        {
            lock (@lock)
            {
                var validationContext = new ValidationContext(this, null, null);
                var validationResults = new List<ValidationResult>();
                Validator.TryValidateObject(this, validationContext, validationResults, true);

                foreach (var kv in errors.ToList())
                {
                    if (validationResults.All(r => r.MemberNames.All(m => m != kv.Key)))
                    {
                        List<string> outLi;
                        errors.TryRemove(kv.Key, out outLi);
                        OnErrorsChanged(kv.Key);
                    }
                }

                var q = from r in validationResults
                        from m in r.MemberNames
                        group r by m into g
                        select g;

                foreach (var prop in q)
                {
                    var messages = prop.Select(r => r.ErrorMessage).ToList();

                    if (errors.ContainsKey(prop.Key))
                    {
                        List<string> outLi;
                        errors.TryRemove(prop.Key, out outLi);
                    }
                    errors.TryAdd(prop.Key, messages);
                    OnErrorsChanged(prop.Key);
                }
            }
        }

        public IEnumerable GetErrors(string propertyName)
        {
            List<string> errorsForName;
            errors.TryGetValue(propertyName, out errorsForName);
            return errorsForName;
        }

        public bool HasErrors
        {
            get { return @errors.Any(kv => kv.Value != null && kv.Value.Count > 0); }
        }

        public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

        protected virtual void OnErrorsChanged(string propertyName)
        {
            var e = ErrorsChanged;
            if (e != null)
                e(this, new DataErrorsChangedEventArgs(propertyName));
        }
    }
}