【问题标题】:WPF - How to implement IDataErrorInfo interface to complex model in ViewModel (FluentValidation)WPF - 如何在 ViewModel 中实现 IDataErrorInfo 接口到复杂模型(FluentValidation)
【发布时间】:2019-05-17 10:07:43
【问题描述】:

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

我不想在我的 ViewModel 中也有很多与模型相同的属性,因此我总是使用复杂的类型,比如 Customer

    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 框架)验证 ViewModel 中的 Customer 类 - 或使用 DataAnnotation 以其他方式验证 - 而无需在 Customer 模型中添加任何额外代码。

提前感谢您指出解决此问题的方法!

【问题讨论】:

    标签: c# wpf mvvm viewmodel idataerrorinfo


    【解决方案1】:

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

    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

    【讨论】:

    • 如何将 FluentValidation 嵌入到这个模型中?我也需要为验证编写单元测试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多