我正在使用 EntLib 6 验证 block 与 WPF 集成。 我的 VM 中的简单属性:
[StringLengthValidator(3, MessageTemplate = "Shorten me!")]
public String SomeText
{
get { return _someText; }
set
{
_someText = value;
OnPropertyChanged("SomeText");
}
}
和相应的文本框绑定(bind):
<TextBox ToolTip="{Binding (Validation.Errors).CurrentItem.ErrorContent, RelativeSource={x:Static RelativeSource.Self}}"
Text="{Binding SomeText, UpdateSourceTrigger=PropertyChanged}"
vab:Validate.BindingForProperty="Text"/>
如果您在 TextBox 中输入了三个以上的字符,该值将被拒绝并存储最后一个有效的字符。 TextBox 以红色突出显示,相应的消息显示为 ToolTip。
在 VM 中,我想检查是否存在任何验证错误 - 但由于该值在 View 中被拒绝,所以一切似乎都很好。那么如何确定是否存在验证错误?
注意:VAB 不使用IDataErrorInfo 接口(interface)!
最佳答案
当您使用 WPF 的内置验证 API 时,我不知道有什么干净直接的方法可以从您的 View 模型中获取验证结果。然而,虽然 VAB 可能不会立即使用 IDataErrorInfo
,但您可以相当轻松地添加集成,并且您只需要修改基本 View 模型类。你可以从这样的事情开始:
public class ValidatingModel : INotifyPropertyChanged, IDataErrorInfo
{
private readonly Dictionary<string, PropertyInfo> _properties;
private readonly Dictionary<string, Validator> _propertyValidators;
private readonly Dictionary<string, ValidationResults> _validationResults;
private string _compositeMessage;
public ValidatingModel()
{
_properties = new Dictionary<string, PropertyInfo>();
_propertyValidators = new Dictionary<string, Validator>();
_validationResults = new Dictionary<string, ValidationResults>();
PopulateValidators();
}
private void PopulateValidators()
{
var properties = GetType().GetProperties(
BindingFlags.Instance |
BindingFlags.Public);
foreach (var property in properties)
{
var attributes = property.GetCustomAttributes(
typeof(ValueValidatorAttribute),
false);
if (attributes.Length == 0 || _properties.ContainsKey(property.Name))
continue;
_properties[property.Name] = property;
_propertyValidators[property.Name] =
PropertyValidationFactory.GetPropertyValidatorFromAttributes(
property.PropertyType,
property,
string.Empty,
new MemberAccessValidatorBuilderFactory());
}
}
protected IEnumerable<ValidationResult> GetValidationResults()
{
foreach (var results in _validationResults.Values)
{
foreach (var result in results)
yield return result;
}
}
protected IEnumerable<ValidationResult> GetValidationResults(string property)
{
if (_propertyValidators.ContainsKey(property))
{
ValidationResults results;
if (!_validationResults.TryGetValue(property, out results))
Validate(property);
if (!_validationResults.TryGetValue(property, out results))
yield break;
foreach (var result in results)
yield return result;
}
}
protected void Validate(string propertyName)
{
if (_propertyValidators.ContainsKey(propertyName))
{
_compositeMessage = null;
_validationResults[propertyName] = Validation.Validate(this);
}
}
string IDataErrorInfo.this[string columnName]
{
get
{
ValidationResults results;
if (!_validationResults.TryGetValue(columnName, out results))
Validate(columnName);
if (_validationResults.TryGetValue(columnName, out results))
return CombineMessages(results);
return null;
}
}
string IDataErrorInfo.Error
{
get
{
if (_compositeMessage != null)
return _compositeMessage;
foreach (var validator in _propertyValidators)
{
if (_validationResults.ContainsKey(validator.Key))
continue;
_validationResults[validator.Key] = ValidateProperty(
validator.Value,
_properties[validator.Key]);
}
_compositeMessage = CombineMessages(
_validationResults.SelectMany(r => r.Value));
return _compositeMessage;
}
}
private ValidationResults ValidateProperty(
Validator validator,
PropertyInfo propertyInfo)
{
return validator.Validate(propertyInfo.GetValue(this, null));
}
private static string CombineMessages(IEnumerable<ValidationResult> results)
{
return results.Aggregate(
new StringBuilder(),
(sb, p) => (sb.Length > 0 ? sb.AppendLine() : sb).Append(p.Message),
sb => sb.ToString());
}
protected void OnPropertyChanged(string propertyName)
{
Validate(propertyName);
var handler = this.PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
只要属性发生变化,此 View 模型就会使用验证应用程序 block API 执行验证,并通过 IDataErrorInfo
报告结果。您需要在 Binding
声明中设置 ValidatesOnDataErrors
才能使其正常工作。
关于c# - 获取验证结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27061980/