Существует несколько способов проверки в WPF.
Я лично предпочитаю многоразовые пользовательские правила проверки, и мне нравится наследовать от Binding
вместо того, чтобы постоянно писать все эти мелочи (например, UpdateSourceTrigger
) в xaml, или использовать раздутый полный синтаксис тегов для добавления правил проверки.
Вы хотите иметь свойство, к которому можно привязать пользовательский текст ошибки проверки. Одна возможность состоит в том, чтобы использовать прикрепленное свойство, к которому вы можете привязать и которое затем используется правилом проверки для возврата ошибки. Мы можем инкапсулировать все в пользовательский класс привязки:
public class Bind : Binding
{
// validation rule
class Rule : ValidationRule
{
public Rule() : base(ValidationStep.RawProposedValue, true) { }
public override ValidationResult Validate(object value, CultureInfo cultureInfo) => ValidationResult.ValidResult;
public override ValidationResult Validate(object value, CultureInfo cultureInfo, BindingExpressionBase owner)
{
if (!string.IsNullOrEmpty((string)value))
return new ValidationResult(false, GetError(owner.Target));
return base.Validate(value, cultureInfo, owner);
}
}
// attached property to hold error text
public static string GetError(DependencyObject obj) => (string)obj.GetValue(ErrorProperty);
public static void SetError(DependencyObject obj, string value) => obj.SetValue(ErrorProperty, value);
public static readonly DependencyProperty ErrorProperty = DependencyProperty.RegisterAttached("Error", typeof(string), typeof(Bind));
// custom binding
public Bind() : base() => Init();
public Bind(string path) : base(path) => Init();
void Init()
{
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
ValidationRules.Add(new Rule());
}
}
Использование в xaml:
<TextBox Text="{local:Bind FirstName}" local:Bind.Error="{Binding FirstNameError}" />
Вы должны назвать Bind
класс более правильно, чтобы отличать его от других привязок , если вы решите следовать моим предпочтениям.
Несколько слов о реализации. Обратите внимание на правило проверки конструктор , необходимо указать, когда мы хотим получить контроль для проверки. В этом случае: когда необработанное значение изменяется в представлении. Другое дело, что нам нужно получить доступ к цели привязки для получения присоединенного свойства, поэтому используется перегрузка с BindingExpression
, а другая (требуется при наследовании от ValidationRule
) просто возвращает.
красный пансион и наконечник инструмента предпочтительнее
По умолчанию Validation.ErrorTemplate
обеспечит красную рамку, и вы можете легко добавить подсказку:
ToolTip="{Binding RelativeSource={RelativeSource self}, Path=(Validation.Errors)[0].ErrorContent}"