Честно говоря, я обнаружил, что запеченные в методах проверки WPF неполные и / или недостаточно элегантные. Я обнаружил, что использование методов WPF разбросало бы код проверки и логику по всему моему приложению и даже поместило бы некоторые в мой интерфейс. Как и вы, я использовал Custom Business Objects (CBO) для всего, и я действительно хотел сохранить свою проверку в своих объектах, поскольку я использовал их в нескольких проектах (веб-сервис, пользовательский интерфейс, мобильный телефон и т. Д.).
Я взял свой CBO (в данном случае Recipe) и добавил несколько методов проверки в качестве свойств. Например:
public Func<string> NameValidation
{
get
{
return () =>
{
string result = null;
if (String.IsNullOrEmpty(Name)) result = "Name cannot be blank";
else if (Name.Length > 100) result = "Name cannot be longer than 100 characters";
return result;
};
}
}
После этого я украсил его пользовательским атрибутом:
[AttributeUsage(AttributeTargets.Property)]
public class CustomValidationMethod : Attribute
{
}
затем я создал метод Validate () для проверки на уровне объекта:
public override void Validate()
{
var a = GetType().GetProperties().Where(w => w.GetCustomAttributes(typeof(CustomValidationMethod), true).Length > 0);
foreach (var a2 in a)
{
var result = a2.GetValue(this, null) as Func<string>;
if (result != null)
{
var message = result();
if (message != null)
//There was an error, do something
else if (message == null && Errors.ContainsKey(a2.Name))
//There was no error
}
}
}
затем я создал пользовательские элементы управления, которые поддерживают мою проверку. В данном случае это был ComboBox, который я извлек из стандартного ComboBox и добавил следующий код:
public Func<string> ValidationMethod
{
get { return (Func<string>) GetValue(ValidationMethodProperty); }
set { SetValue(ValidationMethodProperty, value); }
}
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (ValidationMethod != null && !String.IsNullOrEmpty(ValidationMethod()))
SetControlAsInvalid();
else
SetControlAsValid();
}
После того, как все это настроено, я могу добавить проверку поля в методах проверки (которые хранятся в моих CBO, а не разбросаны по всему коду), я могу добавить проверку уровня объекта в моем методе Validate (). Кроме того, я могу легко настроить поведение элемента управления в отношении проверки.
Чтобы использовать это, в моей виртуальной машине я бы сначала вызвал .Validate (), а затем решил все проблемы перед сохранением. В моем случае, в частности, я буду хранить сообщения об ошибках в коллекции, а затем запрашивать их (это также позволило мне сохранить несколько сообщений об ошибках вместо первого)