我只是在WPF中删除了验证的表面并且遇到了一个可能相当常见的场景:我有一个TextBox,其值需要针对可变数据类型进行验证,具体取决于上下文。例如,如果上下文的数据类型是“int”,则TextBox只需要接受可以转换为Int32的输入。
我的第一个想法是继承ValidationRule类并包含上下文并在重写的Validate函数中使用切换,但我无法绑定任何内容,因为它不是FrameworkElement。
有什么想法吗?
答案 0 :(得分:1)
您可以公开IDataErrorInfo。这使您可以使用复杂的逻辑进行数据验证。
答案 1 :(得分:1)
就我个人而言,我不喜欢将IDataErrorInfo用于这么简单的事情,因为它需要无偿创建一个ViewModel和许多额外的代码,而这些代码都不需要。应该这么简单:
我有一个标记扩展,允许我使用指定为C#表达式的自定义验证代码创建绑定。除了C#解析器之外,这非常简单:只需通过构造一个使用转换器并构建适当验证结构的MultiBinding来实现ProvideValue()。这允许验证表达式除了要验证的值之外还接收包含DataContext和用户指定的Binding对象。
使用此解决方案编码,您可以执行以下操作:
BoundProperty="{my:ValidatedBinding
Path=SomeProperty,
ValidationExpression = context is TextBox ? (int)value>3 : (int)value<7,
Mode=TwoWay,
Converter=...
通过在代码隐藏中创建表达式作为lambda并使用x引用它,您可以轻松地在没有C#解析器的情况下调整我的解决方案:静态:
public static reaonly Expression myValidatorExpression =
(object value, object context, BindingBase binding) =>
context is TextBox ? (int)value>3 : (int)value<7;
...
ValidationExpression={x:Static local:MyClass.myValidatorExpression}
总的来说,我发现这种技术比使用ViewModel更容易,更清晰。当需要进行复杂的转换时,我仍然使用ViewModels,否则只需将纯XAML直接转换为业务对象层。
请注意,此方法假定您的业务对象层不依赖于任何特定的后端存储布局(例如SQL表结构)。如果是这样,更改后端存储将需要更改我的UI,这也是不可取的,因此从这个角度来看,ViewModel是可取的。但如果没有,我总是喜欢保持简单,只使用直接的XAML。