我会将所有验证移至视图模型,这就是它的用途。在视图中包含应用程序逻辑并不是一个好的 MVVM 实践。视图应该是可互换的,无需重新编码验证逻辑。然后,您可以使用绑定到视图模型中的属性的样式中的触发器来更改 TextBox 的外观,而不是使用附加的行为。
有些人使用 IDataErrorInfo 接口。我没有。
创建一个视图模型属性,确定 ZipCodeIsValid 是否:
public bool ZipCodeIsValid
{
get
{
var zipCodeRegex = new Regex("^(?:\d{5})(?:-\d{4})?$");
var zipCodeMatch = zipCodeRegex.Match(ZipCodeText);
return zipCodeMatch.Success;
}
}
每次ZipCodeText
属性更改时,都会为属性引发通知属性更改事件ZipCodeIsValid
。
为您的 TextBox 创建样式:
<Style TargetType="TextBox">
<Setter Property="Foreground" Value="Black"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ZipCodeIsValid}" Value="False">
<Setter Property="Foreground" Value="Black"/>
</DataTrigger>
</Style.Triggers>
</Style>
如果您不想进行那么大的更改并且正在寻找更快的解决方案,您可以将正则表达式字符串移动到静态属性并将它们与附加的行为一起使用,那么您就不会复制正则表达式并且可以使用它们用于测试验证是否通过的视图模型。
使用名为 ZipCode 的静态字符串属性创建一个名为 ValidationRegex 的类:
public class ValidationRegex
{
public static string ZipCode = "^(?:\d{5})(?:-\d{4})?$";
}
将其与附加行为一起使用:
<TextBox h:ColorMaskingTextBoxBehavior.Mask="{x:Static ValidationRegex.ZipCode}"/>
在您的视图模型中使用它:
public void Save()
{
var zipCodeRegex = new Regex(ValidationRegex.ZipCode);
var zipCodeMatch = zipCodeRegex.Match(ZipCodeText);
if (!zipCodeMatch.Success)
{
throw new ValidationException("Zip code is invalid!");
}
}