Я создал свою собственную платформу валидации для 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 содержит коллекцию ошибок:
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);
}