wpf中使用IDataErrorInfo实现数据校验,绑定实体需要实现了此接口,并在UI绑定表达式中添加ValidatesOnDataErrors=True,这样数据校验发生时,wpf会调用该接口中的索引然后返回相应的校验信息,我们为控件添加属性触发器来响应校验。
下面结合我的项目中的一部分代码做一说明,具体效果见 wpf企业级开发中的几种常见业务场景。
UI绑定
<TextBox Text="{Binding EditProduct.Num, ValidatesOnExceptions=True,ValidatesOnDataErrors=True,NotifyOnValidationError=True}" Grid.Column="1"/>
model中的IDataErrorInfo实现
public string this[string columnName] { get { switch (columnName) { case "Num": if (Num.HasNothing()) return "编号不能为空"; if (!OnLogicValidate("Num")) return "编号不能重复"; if (Num.Length > 100) return "长度不能超过100个字符"; break; } return string.Empty; } }
为了将逻辑性的校验转移到ViewModel中,我专门在model的基类中设计了一个事件,OnLogicValidate方法将执行这个事件,比如我在ViewModel中这样使用,这样比较复杂的逻辑校验就转移到VM中了,而model中只保留简单的长度校验、类型校验之类的逻辑。
bool EditProduct_PropertyNeedLogicValidate(string propertyName,Object model) { if (propertyName == "Num" && XDBContext.tb_product.FirstOrDefault(p => p.Num == EditProduct.Num && p.ID != EditProduct.ID) != null) return false; return true; }
最后在控件模板中加入属性触发器用来响应错误,注意还需要设置控件的绑定属性NotifyOnValidationError=True
<Setter Property="Template"> <Setter.Value> <ControlTemplate> <ControlTemplate.Triggers> <Trigger Property="Validation.HasError" Value="true"> <Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self},Path=(Validation.Errors)[0].ErrorContent}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter>