WPF-如何在ViewModel(FluentValidation)中为复杂模型实现IDataErrorInfo接口

时间:2019-05-17 10:07:44

标签: c# wpf mvvm viewmodel idataerrorinfo

我认为我的问题很容易描述-因为我使用的是使用EF的数据库优先方法-我绝对不希望在Model类中包含任何额外的代码,因为在edmx文件中更新数据库时,它消失了(并且独立于EF)。

在我总是使用诸如客户

之类的复杂类型之前,我也不想在ViewModel中具有与模型相同的许多属性。
    public partial class Customer
    {

        public int ID{ get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
}

public class AddCustomerViewModel:ViewModelBase
{
        public Customer Customer
        {
            get { return customer; }
            set { customer = value; RaisePropertyChanged(); }
        }
}

如何使用IDataErrorInfo和CustomerValidator(FluentValidation Framework)或以其他方式使用DataAnnotation在ViewModel中验证Customer类,而在Customer模型中没有任何其他代码。

在此先感谢您指出解决此问题的方法!

1 个答案:

答案 0 :(得分:0)

您可以包装模型并在视图模型中实现验证逻辑:

public class AddCustomerViewModel : ViewModelBase, INotifyDataErrorInfo
{
    private readonly Dictionary<string, ICollection<string>> _validationErrors 
        = new Dictionary<string, ICollection<string>>();
    private readonly Customer _customer;

    public AddCustomerViewModel(Customer customer)
    {
        _customer = customer;
    }

    [Required(ErrorMessage = "You must enter a name.")]
    public string Name
    {
        get { return _customer.Name; }
        set { _customer.Name = value; ValidateModelProperty(value, nameof(Name)); }
    }

    //+ ID and Address

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

        ICollection<ValidationResult> validationResults = new List<ValidationResult>();
        ValidationContext validationContext =
            new ValidationContext(this, 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);
    }

    #region INotifyDataErrorInfo members
    public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
    private void RaiseErrorsChanged(string propertyName) =>
        ErrorsChanged?.Invoke(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 => _validationErrors.Count > 0;
    #endregion

}

顺便说一句,由于.NET Framework 4.5,您应该更喜欢INotifyDataErrorInfo而不是IDataErrorInfo