我使用基于属性的验证为WPF构建了自己的自定义验证框架。我坚持最后一步是突出显示TextBox。实际上,它确实突出显示了文本框,但所有文本框都依赖于单个属性HasError。
public class RegistrationViewModel : ViewModel
{
[NotNullOrEmpty("FirstName should not be null or empty")]
public string FirstName { get; set; }
[NotNullOrEmpty("Middle Name is required!")]
public string MiddleName { get; set; }
[NotNullOrEmpty("LastName should not be null or empty")]
public string LastName { get; set; }
public bool HasError
{
get
{
**return Errors.Count > 0; // THIS IS THE PROBLEM**
}
}
}
这是XAML代码:
<Style x:Key="textBoxStyle" TargetType="{x:Type TextBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=HasError}" Value="True">
<Setter Property="Background" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
上面代码的问题在于它会突出显示所有使用“textBoxStyle”的文本框,即使它们是有效的。这是因为HasError不会基于个别属性进行验证,而是整体验证。
有什么想法吗?
更新1:
ViewModel包含Errors集合:
public class ViewModel : ContentControl, INotifyPropertyChanged
{
public static DependencyProperty ErrorsProperty;
static ViewModel()
{
ErrorsProperty = DependencyProperty.Register("Errors", typeof(ObservableCollection<BrokenRule>), typeof(ViewModel));
}
public ObservableCollection<BrokenRule> Errors
{
get { return (ObservableCollection<BrokenRule>)GetValue(ErrorsProperty); }
set
{
SetValue(ErrorsProperty,value);
OnPropertyChanged("HasError");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}
更新2:
我的验证引擎:
public bool Validate(object viewModel)
{
_brokenRules = new List<BrokenRule>();
// get all the properties
var properties = viewModel.GetType().GetProperties();
foreach(var property in properties)
{
// get the custom attribute
var attribues = property.GetCustomAttributes(typeof (EStudyValidationAttribute), false);
foreach(EStudyValidationAttribute att in attribues)
{
bool isValid = att.IsValid(property.GetValue(viewModel,null));
if(isValid) continue;
// add the broken rule
var brokenRule = new BrokenRule()
{
PropertyName = property.Name,
Message = att.Message
};
_brokenRules.Add(brokenRule);
}
}
var list = _brokenRules.ToObservableCollection();
viewModel.GetType().GetProperty("Errors").SetValue(viewModel,list,null);
return (_brokenRules.Count() == 0);
}
答案 0 :(得分:6)
您可以在ViewModel中实现IDataErrorInfo接口,并在XAML中检查带有验证错误的控件元素的附加属性Validation.HasError;它更好,因为它是.Net中的标准机制。
<Style x:Key="textBoxStyle" TargetType="{x:Type TextBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Validation.HasError}" Value="True">
<Setter Property="Background" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
在TextBoxes中绑定属性时,需要将ValidatesOnDataError绑定属性设置为true。
<TextBox x:Name="someTextBox" Text="{Binding Path=someProperty, ValidatesOnDataErrors=True}">
public class ViewModel : ContentControl, INotifyPropertyChanged,IDataErrorInfo
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
public string this[string propertyName]
{
get
{
return ValidateProperty(this,propertyName);
}
}
public string Error
{
get
{
return "";
}
}
}
您甚至可以使用已实施的验证方法,但请按属性检查验证。
答案 1 :(得分:0)
您可能对 WPF Application Framework (WAF) 和示例应用 BookLibrary 和 EmailClient 感兴趣。他们使用DataAnnotations命名空间中的验证属性以及 IDataErrorInfo 接口。在验证的类中只需要另外两行代码来完成这项工作(例如BookLibrary.Domain / Book.cs)。