我的视图中有一个文本框,用户可以在其中输入TCP端口值。 由于ViewModel提供了完整的绑定模型,因此该文本框直接绑定到Model的Port属性(类型为Int32)。该模型是从ObservableObject继承的,因此直接绑定到它可以很好地工作。
我在模型中使用INotifyDataErrorInfo,并且Port属性会验证属性设置器中的值(该值必须大于0)。
视图中有一个按钮,该按钮绑定到模型的HasError()方法,并根据HasError()的布尔返回值设置其IsEnabled状态
由于此问题,如果用户在“ Hello world”中键入内容,WPF绑定引擎将引发异常。在这种情况下,永远不会执行属性设置器,因此对于此类无效输入,HasError()永远不会更改为true。
在这种情况下,我当然可以为“视图”中的文本框设置“ ValidatesOnExceptions = True”,以至少使该文本框显示其验证错误模板,但是仍然不会禁用该按钮。
问题,如何处理自动转换失败而导致永远不执行ViewModel / Model验证的情况下,推荐的解决方案是什么?
我可以接受这样一种解决方案:在WPF绑定引擎执行将失败的自动类型转换为Int32之前,在文本框字符串而不是Int32类型上执行Validation。
我真正要避免的解决方案是让ViewModel / Model属性始终为字符串类型,在设置器中验证字符串,然后尝试将其手动转换为正确的类型(在这种情况下为Int32)。必须有一个更好的解决方案,避免所有此类手动转换。
使用ValidationRules时,可以告诉Validation引擎在自动转换之前执行ValidationRule。我真正想要的是一种在执行自动强制转换之前也执行INotifyDataErrorInfo验证的方法。
答案 0 :(得分:0)
int
属性不能设置为int
值以外的其他值。当您尝试将其设置为“ Hello world”时,绑定引擎将捕获异常并为您处理。
如果您想自己执行验证或自定义错误消息,则可以定义自定义ValidationRule
并将其ValidationStep
属性设置为RawProposedValue
以便应用在进行值转换之前:
public class StringToIntValidationRule : ValidationRule
{
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
int i;
if (int.TryParse(value.ToString(), out i))
return new ValidationResult(true, null);
return new ValidationResult(false, "Please enter a valid integer value.");
}
}
XAML:
<TextBox>
<TextBox.Text>
<Binding Path="Age" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:StringToIntValidationRule ValidationStep="RawProposedValue"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
请注意,这种验证或自定义不涉及视图模型。这是框架/视图/控件。