C#验证:IDataErrorInfo没有属性名称的硬编码字符串?

C#验证:IDataErrorInfo没有属性名称的硬编码字符串?,c#,wpf,validation,C#,Wpf,Validation,实现IDataErrorInfo的最佳实践是什么?在不使用属性名硬编码字符串的情况下,是否可以实现它 通用验证例程的基类 如果在IDataErrorInfo实现中执行一些Futhing,则可以使用。例如,下面是我经常使用的基本视图模型(来自Windows窗体,但您可以推断): 用法示例: public class LogOnViewModel : ViewModelBase { [DisplayName("User Name")] [Required] [MailAddr

实现
IDataErrorInfo
的最佳实践是什么?在不使用属性名硬编码字符串的情况下,是否可以实现它

通用验证例程的基类 如果在
IDataErrorInfo
实现中执行一些Futhing,则可以使用。例如,下面是我经常使用的基本视图模型(来自Windows窗体,但您可以推断):

用法示例:

public class LogOnViewModel : ViewModelBase
{
    [DisplayName("User Name")]
    [Required]
    [MailAddress] // This is a custom DataAnnotation I wrote
    public string UserName
    {
        get
        {
                return this.userName;
        }
        set
        {
                this.userName = value;
                this.NotifyPropertyChanged("UserName");
        }
    }

    [DisplayName("Password")]
    [Required]
    public string Password
    {
        get; // etc
        set; // etc
    }
}

利用IDataErrorInfo进行一次性验证例程 老实说,我最终使用了注释和开关。我将注释用于简单的验证,如果我有更复杂的注释(例如“如果设置了此其他属性,则仅验证此属性”),那么我将在重写
this[]
索引时使用开关。该模式通常如下所示(只是一个虚构的示例,它不一定有意义:

public override string this[string columnName]
{
    get
    {
        // Let the base implementation run the DataAnnotations validators
        var error = base[columnName];

        // If no error reported, run my custom one-off validations for this
        // view model here
        if (string.IsNullOrWhiteSpace(error))
        {
            switch (columnName)
            {
                case "Password":
                    if (this.Password == "password")
                    {
                        error = "See an administrator before you can log in.";
                    }

                    break;
            }
        }

        return error;
    }

一些意见 至于将属性名指定为字符串:您可以使用lambdas做一些奇妙的事情,但我真诚的建议是,忽略它。。您可能会注意到,在我的
ViewModelBase
中,我的小
NotifyPropertyChanged
助手使用了一些反射魔法,以确保我没有胖指属性名——它可以帮助我消除快速检测数据绑定错误,而不是花20分钟找出我遗漏了什么

您的应用程序将有一系列的验证,从UI属性级别的“必需”或“最大长度”到不同UI级别的“仅在检查其他内容时才需要”,一直到“用户名不存在”在域/持久性级别。您将发现,您必须在UI中重复一点验证逻辑与在域中添加大量元数据以向UI描述自身之间进行权衡,并且您必须权衡如何向用户显示这些不同类别的验证错误

希望这会有所帮助。祝你好运!

对于这种情况(以及
INotifyPropertyChanged
),我倾向于使用私有静态类,将所有属性名称声明为常量:

public class Customer : INotifyPropertyChanging, INotifyPropertyChanged, IDataErrorInfo, etc
{
  private static class Properties
  {
    public const string Email = "Email";
    public const string FirstName = "FirstName";
  }  


}
仍然有一些重复,但在一些项目上对我来说效果很好


至于组织验证,您可以考虑在运行时提供单独的CuultValueActer类。然后,可以针对不同的上下文交换不同的实现。例如,新客户可以与现有的不同的条件进行验证,而无条件混乱。

< P>您可以在接受的ANSWE中找到一些用途。r对于我的问题,专门用于指定属性而不使用字符串。我恐怕无法直接帮助实现
IDataErrorInfo

此接口用于Windows窗体数据绑定。获取属性名称(实际上是列)这不是什么大问题。你确定要在WPF项目中使用它吗?@Hans:是的,我想人们也在WPF中使用它:非常感谢。一个不相关的问题:你能告诉我为什么我们需要
SynchronizationContext
以及应该如何使用它吗?我对并发编程b不是很熟悉我们对此感到好奇。:)WPF和Windows窗体控件和元素不是线程安全的。这意味着,当您与它们交互时,您需要位于创建它们的同一线程上,一个带有消息泵的线程。如果您在后台线程中启动以执行某些工作,然后触摸视图模型的其中一个INotifyPropertyChanged属性,则事件将启动,控件将尝试更新自身,作为错误线程上的事件的结果。SynchronizationContext的Windows窗体实现允许我们将回调封送到正确的线程。如果感到困惑,请忽略它。对于WPF,您应该使用Dispatcher,而不是SynchronizationContext。+1表示使用“胖手指”。我完全要把它添加到我的基类中!
public class Customer : INotifyPropertyChanging, INotifyPropertyChanged, IDataErrorInfo, etc
{
  private static class Properties
  {
    public const string Email = "Email";
    public const string FirstName = "FirstName";
  }  


}