-1

I have been sitting on the internet now for 3hours with not much help. I am trying to implement validation on my UI with the following requirements using the MVVM principle.

Currently by using DataAnnotations on my model: Example:

    private string _name;
    [Required(ErrorMessage = "Name must be filled")]
    public string Name
    {
        get { return _name; }
        set { this.Update(x => x.Name, () => _name= value, _name, value); }
    }

1) I want the validation only to be done when I click on a button (Submit)

2) If I have lets say 5 validations on the UI I want to display them in a list also.

I had a look at several ways and not sure which to use for best practices that suits my 2 requirements the best:

IDataInfoError?

INotifyDataErrorInfo?

DataAnnotations? (Current implementation)

Anybody that can point me in the right direction, tips anything?

user1702369
  • 1,089
  • 2
  • 13
  • 31

1 Answers1

0

You should read the following blog post: https://blog.magnusmontin.net/2013/08/26/data-validation-in-wpf/. It provides an example of you could implement validation using data annotations and the INotifyDataErrorInfo interface:

public class ViewModel : INotifyDataErrorInfo
{
    private readonly Dictionary<string, ICollection<string>>
       _validationErrors = new Dictionary<string, ICollection<string>>();
    private readonly Model _user = new Model();

    public string Username
    {
        get { return _user.Username; }
        set
        {
            _user.Username = value;
            ValidateModelProperty(value, "Username");
        }
    }

    public string Name
    {
        get { return _user.Name; }
        set
        {
            _user.Name = value;
            ValidateModelProperty(value, "Name");
        }
    }

    protected void ValidateModelProperty(object value, string propertyName)
    {
        if (_validationErrors.ContainsKey(propertyName))
            _validationErrors.Remove(propertyName);

        ICollection<ValidationResult> validationResults = new List<ValidationResult>();
        ValidationContext validationContext =
            new ValidationContext(_user, null, null) { MemberName = propertyName };
        if (!Validator.TryValidateProperty(value, validationContext, validationResults))
        {
            _validationErrors.Add(propertyName, new List<string>());
            foreach (ValidationResult validationResult in validationResults)
            {
                _validationErrors[propertyName].Add(validationResult.ErrorMessage);
            }
        }
        RaiseErrorsChanged(propertyName);
    }

    protected void ValidateModel()
    {
        _validationErrors.Clear();
        ICollection<ValidationResult> validationResults = new List<ValidationResult>();
        ValidationContext validationContext = new ValidationContext(_user, null, null);
        if (!Validator.TryValidateObject(_user, validationContext, validationResults, true))
        {
            foreach (ValidationResult validationResult in validationResults)
            {
                string property = validationResult.MemberNames.ElementAt(0);
                if (_validationErrors.ContainsKey(property))
                {
                    _validationErrors[property].Add(validationResult.ErrorMessage);
                }
                else
                {
                    _validationErrors.Add(property, new List<string> { validationResult.ErrorMessage });
                }
            }
        }

        /* Raise the ErrorsChanged for all properties explicitly */
        RaiseErrorsChanged("Username");
        RaiseErrorsChanged("Name");
    }

    public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
    private void RaiseErrorsChanged(string propertyName)
    {
        if (ErrorsChanged != null)
            ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
    }

    public System.Collections.IEnumerable GetErrors(string propertyName)
    {
        if (string.IsNullOrEmpty(propertyName)
            || !_validationErrors.ContainsKey(propertyName))
            return null;

        return _validationErrors[propertyName];
    }

    public bool HasErrors
    {
        get { return _validationErrors.Count > 0; }
    }
}
mm8
  • 163,881
  • 10
  • 57
  • 88