wpf 数据注释、IDataErrorInfo 和 MVVM

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22361803/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 11:12:40  来源:igfitidea点击:

Data Annotations, IDataErrorInfo and MVVM

c#wpfvalidationmvvmdata-annotations

提问by Charles W

I'm trying to find the best way to validate data in MVVM. Currently, I'm trying to use IDataErrorInfo with Data Annotations using the MVVM pattern.

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

However, nothing seems to work and I'm not sure what I could be doing wrong. I have something like this.

但是,似乎没有任何效果,我不确定我做错了什么。我有这样的事情。

Model

模型

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;
    }
}

Model code courtesy of the solution at How to catch DataAnnotations Validation in MVVM(This answer does not meet my criteria unfortunately.)

模型代码由How to catch DataAnnotations Validation in MVVM中的解决方案提供(不幸的是,这个答案不符合我的标准。)

ViewModel

视图模型

public class PersonViewModel
{
    private Person _person;

    public string Name
    {
        get
        {
            return _person.Name
        }
        set
        {
            _person.Name = value;
        }
    }
}



View

看法

<Label Content="Name:" />

<TextBox Text="{Binding UpdateSourceTrigger=LostFocus,
                        Path=Name,
                        ValidatesOnDataErrors=True,
                        NotifyOnValidationError=true}" />


Is there any way to keep the seperation between model, view, and viewmodel while still utilizing data annotations for validation with IDataErrorInfo?


有什么办法可以保持模型、视图和视图模型之间的分离,同时仍然使用数据注释进行 IDataErrorInfo 验证?

回答by Dennis

To keep validation running, IDataErrorInfomust be implemented by the data context, which property is bound to the control. So, it should be something like:

要保持验证运行,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)
    {
        /* ... */
    }
}

There's no need to implement IDataErrorInfoin model, this is view model's responsibility. Usually, IDataErrorInfois implemented by the base class for your view models.

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

By the way, why OnValidateis protected? How do you imagine overriding of this method?

顺便问一下,为什么OnValidate要保护?你如何想象这种方法的覆盖?

回答by Vidas Vasiliauskas

Keep your definition in XAML notifyonvalidation error and validatesondata errors set to true. And in VM use simple Viewmodel which has validation on setter function for desired properties, if validation fails it should throw validation error and xaml will know that it is invalid.

将 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;
        }
    }
}

Now you will need to handle this in xaml and display error text from exception

现在,您需要在 xaml 中处理此问题并显示异常中的错误文本