我正在尝试将模型的属性绑定到openssl
控件上的属性。当属性具有字符串值时,TextBox
会将其呈现为验证消息(首选红色边界和工具提示)。而且,如果该属性具有null或空字符串,则不会呈现任何验证消息。
它看起来像这样:
TextBox
似乎应该像绑定text属性一样容易,但是我似乎无法理解。
答案 0 :(得分:1)
如果您想将 Validation Message 绑定到模型的Property
,我建议您实现INotifyDataErrorInfo
,然后可以随时进行验证,得到错误并显示所需的特定消息,例如,如下所示:
//Model class
[Required]
[CustomValidation(typeof(CustomValidation), "ValidateBirthday")]
public string Birthday
{
get => _birthday;
set => Set(ref _birthday, value);
}
//Custom Validation Class
public static ValidationResult ValidateBirthday(object inObj, ValidationContext inContext)
{
Model model = (Model) inContext.ObjectInstance;
string text = model.Birthday;
DateTime birthday = text.ToDate();
if (birthday == default)
{
return new ValidationResult("Birthday is not valid", new List<string> {"Birthday"});
}
// Future
if (birthday >= DateTime.Now.Date)
{
return new ValidationResult("Birthday is in the future", new List<string> {"Birthday"});
}
// Past
return birthday <= DateTime.Now.Date.AddYears(-200)
? new ValidationResult("Birthday too old", new List<string> {"Birthday"})
: ValidationResult.Success;
}
您只需要验证模型并让消息显示在所需的文本框中:
public void ValidateModel()
{
ValidationContext context = new ValidationContext(this);
List<ValidationResult> results = new List<ValidationResult>();
Validator.TryValidateObject(this, context, results, true);
foreach (KeyValuePair<string, List<string>> valuePair in _validationErrors.ToList())
{
if (!results.All(r => r.MemberNames.All(m => m != valuePair.Key)))
{
continue;
}
_validationErrors.TryRemove(valuePair.Key, out List<string> _);
RaiseErrorChanged(valuePair.Key);
}
IEnumerable<IGrouping<string, ValidationResult>> q = from r in results
from m in r.MemberNames
group r by m
into g
select g;
foreach (IGrouping<string, ValidationResult> prop in q)
{
List<string> messages = prop.Select(r => r.ErrorMessage).ToList();
if (_validationErrors.ContainsKey(prop.Key))
{
_validationErrors.TryRemove(prop.Key, out List<string> _);
}
_validationErrors.TryAdd(prop.Key, messages);
RaiseErrorChanged(prop.Key);
}
}
您可以使用Validation.ErrorTemplate
来绑定并显示消息:
<TextBox Text="{Binding Birthday, UpdateSourceTrigger=PropertyChanged}">
<Validation.ErrorTemplate>
<ControlTemplate>
<StackPanel>
<!-- Placeholder for the TextBox itself -->
<AdornedElementPlaceholder x:Name="textBox"/>
<TextBlock Text="{Binding [0].ErrorContent}" Foreground="Red"/>
</StackPanel>
</ControlTemplate>
</Validation.ErrorTemplate>
</TextBox>
希望有帮助!
答案 1 :(得分:0)
有多种方法可以在WPF中进行验证。
我个人更喜欢可重用的自定义验证规则,并且我喜欢从Binding
继承,而不必在xaml中重复编写所有这些小东西(例如UpdateSourceTrigger
)或使用or肿的全标签语法来添加验证规则。
您想要一个可以绑定自定义验证错误文本的属性。一种可能性是使用可以绑定到的附加属性,然后验证规则将其用于返回错误。我们可以将所有内容封装到自定义绑定类中:
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
类,以区别于其他绑定。
关于实施的几句话。请注意验证规则constructor,它需要指定何时要让控件进行验证。在这种情况下:当原始值在视图中更改时。另一件事是我们需要访问绑定目标以检索附加属性,这就是为什么使用BindingExpression
的重载而另一个(从ValidationRule
继承时需要)重载的原因。
首选红色寄宿生和工具提示
默认Validation.ErrorTemplate
将提供红色边框,您可以轻松添加工具提示:
ToolTip="{Binding RelativeSource={RelativeSource self}, Path=(Validation.Errors)[0].ErrorContent}"
答案 2 :(得分:-2)
希望这对您有帮助
<p>FirstName <span style="color:red;">*</span></p>
@Html.TextBoxFor(model => model.FirstName, htmlAttributes: new { maxlength = "100", autocomplete = "off" })
@Html.ValidationMessageFor(model => model.FirstName)