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