加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 如何显示DataAnnotations的错误消息

发布时间:2020-12-15 22:15:03 所属栏目:百科 来源:网络整理
导读:我花了最后一小时左右的时间用Google搜索来回答这个问题,但几乎每一个结果都是在ASP.NET中或谈论Code First方法,这对我来说是无用的. 我基本上得到了数据库优先的实体框架POCO对象,我正在为使用IDataErrorInfo提供验证. 现在这个工作正常,除了我有一个200行
我花了最后一小时左右的时间用Google搜索来回答这个问题,但几乎每一个结果都是在ASP.NET中或谈论Code First方法,这对我来说是无用的.

我基本上得到了数据库优先的实体框架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验证.也许System.ComponentModel.DataAnnotations.Validator默认情况下不使用MetadataType,但在TypeDescriptor中注册它就像我之前的答案一样应该有效.

Article
Code

我的意思是你必须实现你的validate方法并使用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,null)
                {
                    MemberName = propertyName
                },results);

            if (!result)
            {
                var validationResult = results.First();
                error = validationResult.ErrorMessage;
            }

            return error;
        }

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读