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

标签 c# entity-framework mvvm data-annotations ef-database-first

我花了大约一个小时在谷歌上搜索这个问题的答案,但几乎每个结果都是在 ASP.NET 中或讨论对我无用的 Code First 方法。

我基本上已经获得了数据库优先的 Entity Framework 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

我的意思是您必须实现验证方法并使用 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;
        }

关于c# - 如何显示 DataAnnotations 的错误消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30586350/

相关文章:

c# - 从 VSTO outlook 插件打开 WPF 窗体

c# - MSBUILD:构建包包括额外的文件

c# - 允许用户从按钮立即取消长时间运行的WPF操作

xaml - 有没有办法将参数(或多个参数)传递给 CallMethodAction 行为?

c# - 使 EntityFramework 连接字符串动态化

design-patterns - MVVM 本身是一种观察者模式吗?

c# - 为什么异步函数被调用两次?

c# - 如何在 C# 中访问属性或 const 的 Description 属性?

c# - 将 .Net 实体数据模型与 SQLite 结合使用

c# - 从现有 SQL Server 数据库构建模型时缺少关联