У меня есть ViewModel с некоторыми общедоступными свойствами, которые имеют аннотации данных, например:
[Required]
public string PointOfContact { get; set; }
Что отлично работает. У меня есть вся необходимая сантехника для отображения правильного форматирования элементов управления и сообщений об ошибках в случае сбоя проверки.
Однако у меня есть некоторые поля, требующие условно в зависимости от значения флажка. Например:
public bool Briefing { get; set; }
public DateTime BriefingTime { get; set; }
В этом случае я хочу, чтобы BriefingTime требовался только в том случае, если установлен флажок, привязанный к свойству Briefing. Видимость BriefingTime уже привязана к Briefing, поэтому все, что мне нужно, - это иметь обычное поведение Required при установленном флажке.
Есть ли способ сделать это из коробки или мне нужно написать свой собственный класс аннотации данных? Как бы выглядел такой класс?
Вы можете написать свой собственный ValidationAttribute
:
public class BriefingTimeRequiredAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var model = (MyModel)validationContext.ObjectInstance;
if (model.Briefing && !model.BriefingTime.HasValue)
{
return new ValidationResult("BriefingTime is required.");
}
return ValidationResult.Success;
}
}
Предполагается, что @RobertHarvey MyModel
является моделью, в которой вы определили эти значения, по внешнему виду. Это атрибут, написанный для обработки только проверки одного свойства, а не универсальный валидатор для любого свойства, зависящего от другого свойства.
@Servy: Значит, model.BriefingTime
?
@ Роберт Харви Ага.
ValidationContext
равен нулю.
Можете ли вы опубликовать полный образец кода, включая модель?
В моей ViewModel много кода, но единственные два важных свойства - это Briefing
и BriefingTime
. BriefingTime теперь украшен [BriefingTimeRequired]
. Метод ValidationResult срабатывает правильно, но в ValidationContext
ничего нет.
Попробуйте переопределить это свойство: public override bool RequiresValidationContext { get { return true; } }
в своем пользовательском классе атрибутов проверки.
По-прежнему нулевой. Я думаю, что это конкретное переопределение IsValid
делает некоторые предположения о том, как работает жизненный цикл страницы ASP.NET, предположения, которые недопустимы в WPF.
@RobertHarvey Пожалуйста, покажите нам свой код для проверки. Вы реализовали IDataErrorInfo или INotifyDataErrorInfo
@SirRufo: INotifyDataErrorInfo
. По сути, это эта реализация, Кроме, что я проверяю всю форму только при нажатии кнопки «Сохранить», а не при изменении отдельных свойств. Он отлично работает с атрибутом [Required]
. Мой класс ViewModel унаследован от AnnotationValidationViewModel
.
@RobertHarvey Да, конечно, RequiredAttribute работает, потому что ему не нужен ValidationContext. Реализация важна, потому что теперь мы видим, что вы вызываете метод ValidationAttribute.IsValid без ValidationContext.
@SirRufo: IsValid()
не имеет перегрузки, которая принимает ValidationContext
в качестве параметра, но я понимаю вашу точку зрения. Я изменил реализацию на новый объект ValidationContext
и вызвал Validate()
для атрибута, если для RequiresValidationContext
задано значение true
, и теперь, похоже, он работает. Спасибо.
@RobertHarvey Документация рассказывает нам другую историю. Пожалуйста, нажмите эта ссылка и прочтите. Вы должны увидеть IsValid (объект, ValidationContext) (аргументы два, второй - ValidationContext, а имя метода - Является действительным) - и посмотрите на код этого ответа - это метод отменяет IsValid
@SirRufo: Эта перегрузка недоступна мне в AnnotationValidationViewModel
, моей реализации INotifyDataErrorInfo
, потому что она помечена как protected
. (AnnotationValidationViewModel
не наследуется от ValidationAttribute
, и не должен.)
@RobertHarvey Вы должны проверить с помощью статического класса Валидатор. Это способ вызвать этот защищенный метод IsValid
@SirRufo: Спасибо, я посмотрю.
Откуда у этого класса
Briefing
иBriefingTime
?