【WPF】数据验证
原文:【WPF】数据验证
引言
数据验证在任何用户界面程序中都是不可缺少的一部分.在WPF中,数据验证更是和绑定紧紧联系在一起,下面简单介绍MVVM模式下常用的几种验证方式.
错误信息显示
在介绍数据验证之前,有必要介绍一下如何显示错误信息.方式很简单,定义一个样式触发器,将错误信息和 ToolTip绑定,如下:
<Style TargetType="TextBox">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
</Trigger>
</Style.Triggers>
</Style>
ValidatesOnExceptions验证规则
ValidatesOnExceptions是WPF预定义的验证规则,它会捕捉任何位置上的异常,包括类型转换异常,属性设置器异常,值转换器异常等.捕捉到异常的时候,输入的边框会变成红色,当然也可以自定义错误的模板(Validation.ErrorTemplate).想要ValidatesOnExceptions生效,将绑定属性中的ValidatesOnExceptions设置为true即可.
PS:无论设置为true或false,类型转换异常总会发生的,也就是总会有红色框.
数据对象中验证
直接在数据对象中编写验证规则是最简单粗暴的方式,如下
public int Price
{ get { return _price; }
set
{
if (Equals(value, _price)) return; if (value < )
{ throw new ArgumentException("数值不能小于0"); }
else
{
_price = value;
RaisePropertyChanged(() => Price);
}
}
}
如果小于0,程序不会抛错,文字提示也会显示在ToolTip上,前提是ValidatesOnExceptions=true.
PS:这种方式能如期实现,是因为WPF的Binding 捕捉属性设置中的所有异常.但是,如果是代码设置负数的话,程序直接挂掉.
自定义验证规则
除了WPF预定义的验证规则外,我们还可以自定义验证规则,要继承ValidationRule,编写验证不能大于99的数值,代码如下:
public class NumberRule : ValidationRule
{
public override System.Windows.Controls.ValidationResult Validate(object value, CultureInfo cultureInfo)
{
int i;
// int.TryParse(value.ToString(), out i);
if (!int.TryParse(value.ToString(), out i))
{
return new System.Windows.Controls.ValidationResult(false,
"字符串格式不对!");
}
if (i > )
{
return new System.Windows.Controls.ValidationResult(false,
"数值不能大于99!");
}
else
{
return new System.Windows.Controls.ValidationResult(true, null);
} }
}
<TextBox Height="" Width="" Margin="208,142,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" >
<TextBox.Text>
<Binding Path="Price" Mode="TwoWay" ValidatesOnDataErrors="True">
<Binding.ValidationRules>
<ExceptionValidationRule></ExceptionValidationRule>
<local:NumberRule></local:NumberRule>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
PS:自定义验证规则总是在ExceptionValidationRule之前进行,所以要在NumberRule加上转换类型的异常处理,不然会有抛错的可能性,当然上面的代码中如果有类型错误变量i总会返回0.
PS:验证的执行顺序:自定义验证规则->值转换器->ExceptionValidationRule->数据对象验证.
ValidatesOnDataErrors验证规则
正常情况下,上面的几种方式都可以工作得很好,但是属性多达几十个的时候,写起来就不是那么的舒服了.这个时候我们可以通过继承接口IDataErrorInfo来将我们的验证规则统一起来,代码如下:
public string Error
{ get { return ""; } } public string this[string propertyname]
{
get
{
string result = null;
if (propertyname == "Price")
{
if (Price >99)
{
result = "数值不能大于99!!";
}
}
return result;
}
}
Error在WPF中没作用,返回任意都可以.
PS:记得把ValidatesOnDataErrors=true
PS:验证的执行顺序:自定义验证规则->值转换器->ExceptionValidationRule->数据对象验证->ValidatesOnDataErrors.
进阶 ValidatesOnDataErrors验证规则
ValidatesOnDataErrors虽然能统一起来到一个地方,但是还免不了每一个属性单独写一个规则.所以我们需要一个更简便的方式,那就是DataAnnotations+IDataErrorInfo的方式,代码如下:
private int _price;
[Range(, , ErrorMessage = "数值要在0到99之间")]
public int Price
{ get { return _price; }
set
{
if (Equals(value, _price)) return; if (value < )
{ throw new ArgumentException("数值不能小于0"); }
else
{
_price = value;
RaisePropertyChanged(() => Price);
}
}
} public string this[string propertyname]
{
get
{
var vc = new ValidationContext(this, null, null);
vc.MemberName = propertyname;
var res = new List<System.ComponentModel.DataAnnotations.ValidationResult>(); var result = Validator.TryValidateProperty(this.GetType().GetProperty(propertyname).GetValue(this, null), vc, res);
if (res.Count > )
{
return string.Join(Environment.NewLine, res.Select(r => r.ErrorMessage).ToArray());
}
return string.Empty;
}
}
采用这种方式,开发的时候只需要简单的设置一下特性,就能如期望的显示我们的验证提示了,关于这种方式的详细用法,网上有一篇更好的文章:传送门.
注意事项
到这里,如果没有什么意外,相信大家都会采用DataAnnotations+IDataErrorInfo的方式,这种方式实现最简单,而且发生在viewmodel上,我们很容易地在保存环节得到所有异常信息,从而阻止保存数据的进行.但是WPF的数据验证中都有个通病,就是发生数据异常的时候,属性实际的值还是上次合法的值,和界面上显示的值有所不同.这个时候如果用户强行保存,我们就发现DataAnnotations+IDataErrorInfo的验证方式竟然通过了!这不符合我们的期望.这种情况我没发现有什么优雅的解决方案,暂时想到的只有在按钮的点击事件中遍历LogicalTreeHelper的输入控件,检查Validation.HasError属性,组合异常信息传给viewmodel,让viewmodel作出处理.其实最为彻底的方式是,封装数字输入控件等各类特定的控件,提高用户体验的同时,也让异常处理更简单.
小结
本文简单介绍了WPF数据验证的各种方式,而我们基本上都会采用 DataAnnotations+IDataErrorInfo的方式,如果您有更好的方式,请不吝指教,感激不尽!
【WPF】数据验证的更多相关文章
- wpf数据验证实例及常用方法小结
虽然标题是wpf数据验证,但并不是对IDataErrorInfo.ValidationRule.属性中throw Exception这几种验证方式的介绍: 之前做项目时(例如员工工资管理),根据员工编 ...
- WPF数据验证方式
WPF有两种数据验证的方式: 1 在数据对象上进行验证:普通属性验证或者实现IDataErrorInfo接口 2 可以再绑定规则上进行验证:ExceptionValidationRule异常验证规则 ...
- WPF数据验证
当填写表单时,需要对填写的内容进行验证,检查数据是否符合要求,比如字符串的长度.日期的格式.数字等.WPF支持自定义验证规则,并提供可视化反馈,以便在输入无效值时向用户发出通知. 下面的示例将演示一个 ...
- WPF数据验证(4)——响应与获取验证错误
1780 前面的示例中,有关用户接受到错误的唯一指示是在违反规则的文本框周围的红色轮廓.为了提供更多信息,可以处理 Error 事件,但存储或清除错误时会引发该事件,但前提是必须确保已将 Bindin ...
- WPF数据验证(5)―― 错误模板
<Style TargetType="{x:Type TextBox}"> <Setter Property="Validatio ...
- WPF中的数据验证
数据验证 WPF的Binding使得数据能够在数据源和目标之间流通,在数据流通的中间,便能够对数据做一些处理. 数据转换和数据验证便是在数据从源到目标 or 从目标到源 的时候对数据的验证和转换. V ...
- WPF MVVM从入门到精通8:数据验证
原文:WPF MVVM从入门到精通8:数据验证 WPF MVVM从入门到精通1:MVVM模式简介 WPF MVVM从入门到精通2:实现一个登录窗口 WPF MVVM从入门到精通3:数据绑定 WPF M ...
- WPF MVVM(Caliburn.Micro) 数据验证
书接前文 前文中仅是WPF验证中的一种,我们暂且称之为View端的验证(因为其验证规是写在Xaml文件中的). 还有一种我们称之为Model端验证,Model通过继承IDataErrorInfo接口来 ...
- [WPF] 在 ViewModel 中让数据验证出错(Validation.HasError)的控件获得焦点
1. 需求 在 MVVM 中 ViewModel 和 View 之间的交互通常都是靠 Icommand 和 INotifyPropertyChanged,不过有时候还会需要从 MVVM 中控制 Vie ...
随机推荐
- [iOS] UICollectionView实现图片水平滚动
最新更新: 简单封装了一下代码,参考新文章:UICollectionView实现图片水平滚动 先简单看一下效果: 新博客:http://wossoneri.github.io 准备数据 首先先加入一些 ...
- [Android] 布局优化技巧
看了一些关于优化布局的资料,了解了很多平时不怎么注意的问题,于是把资料整理了一下,一部分内容是翻译来的,一部分是自己理解加上的.每部分内容都有demo,有些资料里的demo比较好的,我就直接拿来用了: ...
- 使用 Azure 资源管理器向 Windows VM 应用策略
通过使用策略,组织可以在整个企业中强制实施各种约定和规则. 强制实施所需行为有助于消除风险,同时为组织的成功做出贡献. 本文介绍如何使用 Azure 资源管理器策略,为组织中的虚拟机定义所需的行为. ...
- Oracle EBS OPM 查询现有量
--查询现有量 --created by jenrry DECLARE p_inventory_item_id NUMBER := 231652; --NOT NULL p_organization_ ...
- 检测到在集成的托管管道模式下不适用的 ASP.NET 设置
system.webServer节点下加上 <validation validateIntegratedModeConfiguration="false" />
- cron定时任务介绍
什么是cron? Cron是linux系统中用来定期执行或指定程序任务的一种服务或软件.与它相关的有两个工具:crond 和 crontab.crond 就是 cron 在系统内的宿主程序,cront ...
- python基础学习15----异常处理
异常处理,是编程语言或计算机硬件里的一种机制,用于处理软件或信息系统中出现的异常状况(即超出程序正常执行流程的某些特殊条件). 1.异常的类型 异常的类型多种多样,常见的异常有: AttributeE ...
- ansible 碎记录
https://www.zhukun.net/archives/8167 ansible -i new/hosts new -m authorized_key -a "user=root k ...
- Docker容器学习与分享02
1.docker容器的创建 首先运行一个centos容器,感受一下Docker容器的便捷 首先先看一下镜像仓库 发现仓库里没有镜像,也就是没有创建容器的模板,这时考虑从REPOSITORY中拉取镜像( ...
- 关于idea通过smalidea无源调试apk
idea 14.0.2 可以使用 smalidea 0.03 单步时,只能按照源码中的行号(line xxx)指定的行跳动, 可以使用鼠标选中变量即时查看变量值 idea 16/17 可以使用smal ...