这就是我要做的。
Windows 窗体上的 DataGrid 控件可以从实现 IDataErrorInfo 的对象中读取错误
正如 MSDN 所说。
IDataErrorInfo 提供了提供用户界面可以绑定到的自定义错误信息的功能。
您在网格数据源集合中的 POCO 对象应该实现 IDataErrorInfo 让我们这样说:
public class MyEntity : IDataErrorInfo
{
public string this[string columnName]
{
get
{
// here you can validate each property of your class (POCO object)
var result = string.Join(Environment.NewLine, Validator.Validate(this, columnName).Select(x => x.ErrorMessage));
return result;
}
}
public string Error
{
get
{
// here you can errors related to the whole object (ex: Password, and PasswordConfirmation do not match)
return string.Join(Environment.NewLine, Validator.Validate(this)
.Select(x => x.ErrorMessage));
}
}
public Boolean IsValid
{
get { return string.IsNullOrEmpty(Error); }
}
}
然后你可以使用一些验证技术来设置你的验证规则。
我喜欢使用DataAnnotation 来实现我的验证逻辑。
所以,假设您的班级有一个不能为空的属性(名称),您的班级可能是:
public class MyEntity : IDataErrorInfo
{
[Required]
public string Name { get; set; }
public string this[string columnName]
{
get
{
// here you can validate each property of your class (POCO object)
var result = string.Join(Environment.NewLine, Validator.Validate(this, columnName).Select(x => x.ErrorMessage));
return result;
}
}
public string Error
{
get
{
// here you can validate errors related to the whole object (ex: Password, and PasswordConfirmation do not match)
return string.Join(Environment.NewLine, Validator.Validate(this)
.Select(x => x.ErrorMessage)
.Union(ModelError.Select(m => m.Value)));
}
}
public Boolean IsValid
{
get { return string.IsNullOrEmpty(Error); }
}
}
那么如果你使用这样的验证器
public class Validator : IValidator
{
public IEnumerable<ErrorInfo> Validate(object instance)
{
IEnumerable<ErrorInfo> errores = from property in instance.GetType().GetProperties()
from error in GetValidationErrors(instance, property)
select error;
if (!errores.Any())
{
errores = from val in instance.GetAttributes<ValidationAttribute>(true)
where
val.GetValidationResult(null, new ValidationContext(instance, null, null)) !=
ValidationResult.Success
select
new ErrorInfo(null,
val.GetValidationResult(null, new ValidationContext(instance, null, null)).ErrorMessage,
instance);
}
return errores;
}
public IEnumerable<ErrorInfo> Validate(object instance, string propertyName)
{
PropertyInfo property = instance.GetType().GetProperty(propertyName);
return GetValidationErrors(instance, property);
}
private IEnumerable<ErrorInfo> GetValidationErrors(object instance, PropertyInfo property)
{
var context = new ValidationContext(instance, null, null);
context.MemberName = property.Name;
IEnumerable<ErrorInfo> validators = from attribute in property.GetAttributes<ValidationAttribute>(true)
where
attribute.GetValidationResult(property.GetValue(instance, null), context) !=
ValidationResult.Success
select new ErrorInfo(
property.Name,
attribute.FormatErrorMessage(property.Name),
instance
);
return validators.OfType<ErrorInfo>();
}
}
根据错误,错误将出现在每个单元格或每行的网格上。
请注意,如果您计划内联编辑您的对象,您还应该实现 INotifyPropertyChanged。
这种方法的好处是将验证逻辑与用户界面分离。