我有一个WPF应用程序,它使用ObservableValidator
来处理使用数据注解的属性验证。这对于string
属性非常有效。例如:
public class LoginViewModel : ObservableValidator
{
[ObservableProperty]
[NotifyDataErrorInfo]
[Required]
[StringLength(64, MinimumLength = 8)]
private string username = String.Empty;
[RelayCommand]
private void LogIn()
{
ValidateAllProperties();
if(HasErrors)
{
return;
}
// Log in the user
}
// ...
}
当我使用<TextBox Text="{Binding Username, ValidatesOnNotifyDataErrors=True}" />
将Username
属性绑定到一个文本框时,我会在视图中自动获得验证消息,这些消息会出现在文本框周围!
但是,我不知道如何处理需要验证非字符串属性的情况。例如:
public class User : ObservableValidator
{
[ObservableProperty]
[NotifyDataErrorInfo]
[Required]
[Range(0, 200)]
private int age = 10;
}
如果我使用与<TextBox Text="{Binding Age, ValidatesOnNotifyDataErrors=True}" />
相同的方法,并且用户输入的值不是像"12aaa"
这样的整数,则绑定上的默认值转换器将抛出一个异常,表明"12aaa" cannot be converted into an integer
。这些值转换异常无法从我的视图模型中检测到,因为绑定引擎从不更新属性值。
因此,即使用户输入了无效数据,调用ValidateAllProperties()
也会将HasError
设置为false
!
我看到了几种处理这种无法检测到的错误的方法:
1.防止用户输入无效数据。这在一开始似乎是可行的,但是对于更复杂的类型(例如,用户输入TimeSpan
)变得更难。
1.为每个非字符串属性添加字符串字段。即使这样做,我也不知道如何将验证错误从类型化属性传播到非类型化属性,以便它们显示在相应的文本框周围。
1.可能还有其他我没想到的选择。
对于MVVM Toolkit的ObservableValidator
,有没有处理非字符串属性转换错误的推荐方法?提前感谢您的帮助!
3条答案
按热度按时间tyu7yeag1#
您应该尝试自定义验证方法或自定义验证属性。
llmtgqce2#
如何使用CustomValidation?
bpzcxfmw3#
这是一个运行时异常,不是由您使用的库引发的。在 * 将值赋给源属性之前 * 抛出异常(当绑定引擎尝试从目标类型
string
转换为源类型int
时)。该异常与数据验证无关。TextBox.Text
的类型为string
。User.Age
的类型为int
。引发异常的原因是绑定试图将TextBox
中的string
值赋给int
属性。没有从string
到int
的隐式转换。如果源属性类型与目标属性类型不同(并且没有隐式类型转换),Binding
标记扩展将使用默认转换器,例如:可以将int
值发送/分配给string
绑定目标属性。但这仅在存在默认转换的情况下有效。例如,
"123"
是纯数字,可以使用默认转换器转换为int
。但是"123abc"
是字母数字的,到int
的标准转换失败,绑定引擎抛出异常。您可以:
1.使
User.Age
的类型为string
1.添加
string
类型的User.AgeText
属性以绑定到TextBox
,并在数据模型中将其转换为int
(例如使用属性设置器中的int.TryParse
)1.实现一个
IValueConverter
,将绑定目标值从string
转换为int
,例如:使用int.TryParse
1.扩展
TextBox
并实现例如NumericTextBox
,其中输入从string
转换为int
,或者验证输入以确保有效的数值(以便默认转换器可以处理它)。值本身的验证(例如如果数值在特定范围内)仍然在数据源(视图模型类)中实现