数据注解,IDataErrorInfo和MVVM

本文关键字:MVVM IDataErrorInfo 数据 | 更新日期: 2023-09-27 17:49:56

我试图找到在MVVM中验证数据的最佳方法。目前,我正试图使用IDataErrorInfo与数据注释使用MVVM模式。

然而,似乎没有工作,我不知道我可能做错了什么。我有这样的东西

<标题>
public class Person : IDataErrorInfo
{
    [Required(ErrorMessage="Please enter your name")]
    public string Name { get; set; }
    public string Error
    {
        get { throw new NotImplementedException(); }
    }
    string IDataErrorInfo.this[string propertyName]
    {
        get
        {
            return OnValidate(propertyName);
        }
    }
    protected virtual string OnValidate(string propertyName)
    {
        if (string.IsNullOrEmpty(propertyName))
            throw new ArgumentException("Property may not be null or empty", propertyName);
        string error = string.Empty;
        var value = this.GetType().GetProperty(propertyName).GetValue(this, null);
        var results = new List<ValidationResult>();
        var context = new ValidationContext(this, null, null) { MemberName = propertyName };
        var result = Validator.TryValidateProperty(value, context, results);
        if(!result)
        {
            var validationResult = results.First();
            error = validationResult.ErrorMessage;
        }
        return error;
    }
}

模型代码由如何在MVVM中捕获数据注释验证的解决方案提供(不幸的是,这个答案不符合我的标准。)

<标题> ViewModel h1>
<标题> 视图
<Label Content="Name:" />
<TextBox Text="{Binding UpdateSourceTrigger=LostFocus,
                        Path=Name,
                        ValidatesOnDataErrors=True,
                        NotifyOnValidationError=true}" />


是否有任何方法可以保持模型,视图和视图模型之间的分离,同时仍然利用数据注释与IDataErrorInfo进行验证?

数据注解,IDataErrorInfo和MVVM

为了保持验证运行,IDataErrorInfo必须由数据上下文实现,该属性绑定到控件。所以,它应该是这样的:

public class PersonViewModel : IDataErrorInfo 
{
    [Required(AllowEmptyStrings = false)]
    public string Name
    {
        get
        {
             return _person.Name
        }
        set
        {
             _person.Name = value;
        }
    }    
    public string Error
    {
        get { throw new NotImplementedException(); }
    }
    string IDataErrorInfo.this[string propertyName]
    {
        get
        {
            return OnValidate(propertyName);
        }
    }
    protected virtual string OnValidate(string propertyName)
    {
        /* ... */
    }
}

不需要在模型中实现IDataErrorInfo,这是视图模型的责任。通常,IDataErrorInfo是由视图模型的基类实现的。

顺便问一下,为什么OnValidate是受保护的?你如何想象重写这个方法?

将您在XAML中的定义notifyonvalidation error和validatesondata errors设置为true。在VM中,使用简单的Viewmodel,它对所需属性的setter函数有验证,如果验证失败,它应该抛出验证错误,xaml将知道它是无效的。

public class PersonViewModel
{
    private Person _person;
    public string Name
    {
        get
        {
            return _person.Name
        }
        set
        {
            if(value == string.empty)
               throw new ValidationException("Name cannot be empty");
            _person.Name = value;
        }
    }
}
现在您需要在xaml中处理这个问题,并从异常
中显示错误文本