提问人:hackeyzach 提问时间:6/17/2023 最后编辑:hackeyzach 更新时间:6/23/2023 访问量:1144
MVVM 社区工具包:将 ObservableValidator 与非字符串属性结合使用
MVVM Community Toolkit: Using ObservableValidator with non-string properties
问:
我有一个 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
}
// ...
}
当我使用 将属性绑定到文本框时,我会自动在我的视图中获取显示在文本框周围的验证消息!Username
<TextBox Text="{Binding Username, ValidatesOnNotifyDataErrors=True}" />
但是,我不知道我应该如何处理需要验证非字符串属性的情况。例如:
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
我看到了一些方法来处理这些无法检测到的错误:
- 防止用户输入无效数据。这起初似乎是可行的,但对于更复杂的类型(例如,用户输入的 )。
TimeSpan
- 为每个非字符串属性添加字符串字段。即使您这样做,我也不知道如何将验证错误从类型化属性传播到非类型化对应项,以便它们显示在相应的文本框周围。
- 可能是我没有想到的其他选择。
是否有任何推荐的方法来处理 MVVM 工具包的非字符串属性的转换错误?提前感谢您的帮助!ObservableValidator
答:
评论
这是一个运行时异常,不是由您使用的库引发的。在将值分配给 source 属性之前(当绑定引擎尝试从目标类型转换为源类型时)将引发异常。该异常与数据验证无关。string
int
TextBox.Text
是 的 类型 。 是 的 类型 。引发异常的原因是绑定尝试将值从 分配给属性。没有隐式强制转换 from to 。如果源属性类型与目标属性类型不同(并且没有隐式类型转换),则标记扩展将使用默认转换器,以便例如,可以将值发送/分配给绑定目标属性。但这仅在存在默认转换时才有效。string
User.Age
int
string
TextBox
int
string
int
Binding
int
string
例如,是纯数字,可以转换为使用默认转换器。但是是字母数字,并且标准转换为失败,绑定引擎抛出异常。"123"
int
"123abc"
int
您可以:
- 类型品牌
User.Age
string
- 添加要绑定的类型的属性,并将其转换为数据模型中的属性,例如,使用 from the property setter
User.AgeText
string
TextBox
int
int.TryParse
- 实现一个 将绑定目标值从 转换为 ,例如借助 。
IValueConverter
string
int
int.TryParse
- 扩展和实现例如 其中,输入从 转换为 或验证输入以确保有效的数值(以便默认转换器可以处理它)。值本身的验证(例如,如果数值在特定范围内)仍然在数据源(视图模型类)中实现
TextBox
NumericTextBox
string
int
评论
NumericTextBox
如何使用 CustomValidation?
public partial class LoginViewModel : ObservableValidator
{
public LoginViewModel()
{
ValidateAllProperties();
}
[ObservableProperty]
[NotifyDataErrorInfo]
[Required]
[StringLength(64, MinimumLength = 8)]
private string? username = String.Empty;
[ObservableProperty]
[NotifyDataErrorInfo]
[Required]
[Range(0, 200)]
[CustomValidation(typeof(LoginViewModel), nameof(ValidateAge))]
private string? age = "10";
public static ValidationResult ValidateAge(string age, ValidationContext context)
{
if (int.TryParse(age, out int number))
{
return ValidationResult.Success;
}
return new("Validation failed/show error message");
}
[RelayCommand]
private void LogIn()
{
ValidateAllProperties();
if (HasErrors)
{
return;
}
// Log in the user
}
}
评论