如何显示DataAnnotations的错误消息

本文关键字:DataAnnotations 错误 消息 显示 何显示 | 更新日期: 2023-09-27 17:51:24

我花了一个小时左右的时间在谷歌上寻找这个问题的答案,但几乎每个结果都是在ASP中。或者谈论代码优先的方法,这对我来说毫无用处。

我基本上有数据库第一实体框架POCO对象我提供验证使用IDataErrorInfo

现在工作得很好,除了我有一个索引器,它有200行长,里面有大约40个if语句。(我是认真的。)

我现在正在做的是像这样扩展类:

public partial class MyPocoObject : IDataErrorInfo
{
    public string Error
    {
        get { throw new NotImplementedException("IDataErrorInfo.Error"); }
    }
    public string this[string columnName]
    {
        get
        {
            string result = null;
            // There's about 40 if statements here...
        }
    }
}

显然,这是错误的,所以我试图使用DataAnnotations代替。

这是我目前所理解的。

我已经创建了这样的元数据类:

[MetadataType(typeof(MyObjectMetaData))]
public partial class MyObject { }
public class MyObjectMetaData
{
    [Required(AllowEmptyStrings = false, ErrorMessage = "Forename is a required field.")]
    public string Forename;
}

然后我有这样的控件声明:

<TextBox Text="{Binding SelectedObject.Forename, NotifyOnValidationError=True, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}"/>

那么我在别处有一个触发器:

<Style TargetType="TextBox" BasedOn="{StaticResource Global}">
    <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="true">
            <Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self},Path=(Validation.Errors)[0].ErrorContent}"/>
        </Trigger>
    </Style.Triggers>
</Style>

当我使用IDataErrorInfo这样做时,当验证失败时,我将得到一个红色边框和一个带有错误消息的工具提示。使用数据注释,我什么也得不到。

我应该如何实现这个?因为在一个方法中使用40个if语句太疯狂了。

更新:我已经尝试了答案中建议的代码,这些代码不起作用,尽管我认为我做错了。

public partial class Member : IDataErrorInfo
{
    // Error: The type 'Project.Client.Models.Member' already contains a definition for 'Forename'
    [Required(AllowEmptyStrings = false, ErrorMessage = "Forename is a required field.")]
    public string Forename;
    private readonly Dictionary<string, object> _values = new Dictionary<string, object>();
    public string Error
    {
        get { throw new NotImplementedException("IDataErrorInfo.Error"); }
    }
    public string this[string columnName]
    {
        get { return OnValidate(columnName); }
    }

    protected virtual string OnValidate(string propertyName)
    {
        if (string.IsNullOrEmpty(propertyName))
        {
            throw new ArgumentException("Invalid property name", propertyName);
        }
        string error = string.Empty;
        // Error: Project.Client.Models.Member.GetValue<T>(string)' cannot be inferred from the usage. Try specifying the type arguments explicitly
        var value = GetValue(propertyName);
        var results = new List<System.ComponentModel.DataAnnotations.ValidationResult>(1);
        var result = Validator.TryValidateProperty(
            value,
            new ValidationContext(this, null, null)
            {
                MemberName = propertyName
            },
            results);
        if (!result)
        {
            var validationResult = results.First();
            error = validationResult.ErrorMessage;
        }
        return error;
    }
    protected T GetValue<T>(string propertyName)
    {
        if (string.IsNullOrEmpty(propertyName))
        {
            throw new ArgumentException("Invalid property name", propertyName);
        }
        object value;
        if (!_values.TryGetValue(propertyName, out value))
        {
            value = default(T);
            _values.Add(propertyName, value);
        }
        return (T)value;
    }
}
更新2:

在文章中链接的代码MVVM似乎工作,但没有错误信息仍然显示,即使OnValidate正在触发。

虽然现在有些事情是错误的…即使文本框的内容在变化,从GetValue返回的值始终是相同的,并且在没有从数据库加载的空对象上,验证根本不会触发。

如何显示DataAnnotations的错误消息

看来您必须手工集成DataAnnotations验证。也许System.ComponentModel.DataAnnotations.Validator默认不使用元数据类型,但在TypeDescriptor中注册它,就像我之前的回答应该工作。

的文章代码

我的意思是你必须实现你的验证方法并使用System.ComponentModel.DataAnnotations.Validator。

查看PropertyChangedNotification实现的源代码,我链接:

/// <summary>
        /// Validates current instance properties using Data Annotations.
        /// </summary>
        /// <param name="propertyName">This instance property to validate.</param>
        /// <returns>Relevant error string on validation failure or <see cref="System.String.Empty"/> on validation success.</returns>
        protected virtual string OnValidate(string propertyName)
        {
            if (string.IsNullOrEmpty(propertyName))
            {
                throw new ArgumentException("Invalid property name", propertyName);
            }
            string error = string.Empty;
            var value = GetValue(propertyName);
            var results = new List<System.ComponentModel.DataAnnotations.ValidationResult>(1);
            var result = Validator.TryValidateProperty(
                value,
                new ValidationContext(this, null, null)
                {
                    MemberName = propertyName
                },
                results);
            if (!result)
            {
                var validationResult = results.First();
                error = validationResult.ErrorMessage;
            }
            return error;
        }

我最终通过绑定到视图模型(而不是模型本身)中的属性并将注释添加到视图模型(而不是试图扩展和混乱模型)来解决这个问题。

想想看,我可能应该先这么做....

一些。net技术检索和处理元数据类型,而另一些则没有。

在使用之前尝试注册好友类:

var myObjectMetadaProviderProvider = new 
    AssociatedMetadataTypeTypeDescriptionProvider(
        typeof(MyObject),
        typeof(MyObjectMetaData));
TypeDescriptor.AddProvider(myObjectMetadaProviderProvider , typeof(MyObject));

这允许以透明的方式检索在伙伴类中声明的属性,而不必知道主类中的元数据类型。