[WPF]Binding的Converter和Validator
不拘一格用数据的Converter
上篇文已经说明,Binding就是数据源与目标之间的“关联”。大多数情况下,数据从Source到Target以及从Target返回Source都是“直来直去”的,但有些场景却需要我们对数据做些转换才能为我所用。举两个典型的例子:
- 如果数据源里的值是Y和N,如果是Y,那么UI上的CheckBox就被勾选,否则就不勾选,这就需要我们把string(也许是char)类型的数据转换成bool?类型再使用。如果Binding是TwoWay的,CheckBox的勾选操作还会把值传回数据源。
- 如果“评论内容”TextBox里没有内容,则“提交”Button不可以点击。这是个典型的OneWay数据Binding,因为只有TextBox去影响Button的份儿。具体如何实现,大家可以先猜猜;)
想要实现这类的转换,就需要为Binding这个“绿色通道”设置“关卡”,这里我们用到的关卡就是“数据转换器”(Data Converter)。Converter实际上就是一个类,它这个类有个要求——它需要实现IValueConverter这个接口。这个接口的内容非常简单——只有两个方法,它们分别是:
- Convert方法:按照你的要求,把从数据源传来的数据转成你想要的数据——至于是加减乘除还是煎炒炸炖,那就要看你怎么实现函数体了
- ConvertBack方法:如果Binding是TwoWay的,那么数据目标会回传经用户改动后的数据,这时候你就不得不把数据转换回数据源里的格式——大多数情况下,它是Convert方法的逆运算,具体情况还要具体分析。(不过,熟饭估计怎么着也变不成生米了,呵呵~~)
下面是第一个例子的核心代码,我来一步一步实现。
第一步:先声明一个类。我的习惯是用Converter开头,后缀是“源类型2目标类型”,这里的“2”是“to”的意思。
- class ConverterYN2TF
- {
- }
第二步:让这个类实现IValueConverter接口。这里有个使用VS2008的小窍门——在类名后写上“:IValueConverter”后,按下键盘上的“Shift+Alt+F10”会弹出VS2008的智能菜单,选择其中的第一项“实现IValueConverter的方法”,VS2008会自动为我们生成需要实现的方法体:
- class ConverterYN2TF : IValueConverter
- {
- #region IValueConverter Members
- public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
- {
- throw new NotImplementedException();
- }
- public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
- {
- throw new NotImplementedException();
- }
- #endregion
- }
第三步:添加Attribute。这步不是必需的,但加上有是有好处的——告诉Converter数据的源类型与目标类型各是什么。值得注意的是,CheckBox的IsChecked属性是bool?类型的(可空bool类型),意思是说可以是True/False/Null三种值,表现在UI上就是勾选/不勾选/中间态。如果想让CheckBox能显示中间态,需要把它的IsThreeState属性设为True。
- [ValueConversion(typeof(string), typeof(bool?))] //数据的源类型是string,目标类型是bool?
- class ConverterYN2TF : IValueConverter
- {
- #region IValueConverter Members
- public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
- {
- throw new NotImplementedException();
- }
- public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
- {
- throw new NotImplementedException();
- }
- #endregion
- }
第四步:实现这两个方法。在开始动手前,我们先分析一下这两个方法的参数和返回值。
首先,这两个方法的参数和返回值都是object类型的,之所以这样做,是因为接口的设计者并不知道你要传入和传出的数据是什么类型的,只好用它们“绝对正确”的基类——object了。
其次,对于Convert方法来说, value是从数据源传来的数据,返回值是转换好后发送给数据目标的数据。对于ConvertBack方法正好反过来,value是从数据目标(比如UI)传回来的数据,返回值是要与数据源匹配的数据。
再次,偶尔我们会用到parameter那个参数。比如在转换某些数据的时候,我们需要依赖一些其它的外部数据来辅助我们的数据转换,这时候就可以在parameter上打主意了。如果想传多个参数的话,可以把这些参数打包成数组或者class/struct等数据结构再传进来。在我们工作的代码中用到过一次parameter,我为我的Converter类准备了一个带参数的构造函数,把外部的辅助数据传给Converter
最后,如果你的Binding是OneWay的,那么恭喜你——你的ConvertBack函数体随便怎么实现都可以——因为它不可能被调用。
完成的类是这样的:
- [ValueConversion(typeof(string), typeof(bool?))] //数据的源类型是string,目标类型是bool?
- class ConverterYN2TF : IValueConverter
- {
- public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
- {
- string str = System.Convert.ToString(value);
- switch (str)
- {
- case "Y":
- return true;
- case "N":
- return false;
- default:
- return null;
- }
- }
- public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
- {
- bool? b = System.Convert.ToBoolean(value);
- switch (b)
- {
- case true:
- return "Y";
- case false:
- return "N";
- default:
- return "Null";
- }
- }
- }
使用这个类的方法是将Binding实例的Converter属性设置为这个类的一个实例:
- checkBox1.IsThreeState = true;
- Binding binding = new Binding("Text");
- binding.Source = textBox1;
- binding.Converter = new ConverterYN2TF(); // 设定Converter
- this.checkBox1.SetBinding(CheckBox.IsCheckedProperty, binding);
至于上面的第二个例子,留给大家自己动手去实现吧。想一想:怎样才能让Button的IsEnable属性与TextBox中文本的有无关联上呢?
让数据“干干净净”的Validation
再让我们来看看如何对数据进行“安检”。
首先,这里有一个“霸王条款”——Binding认为从数据源出去的数据都是“干净”的,所以不进行校验;只有从数据目标回传的数据才有可能是“脏”的,需要校验。
其次,对于一个Binding而言,Converter只能有一个,而校验条件可以是好几个——它们存储在Binding的ValidationRules这个集合里。其实,数据校验与转换做的事儿差不多。
下面给出一个例子:我们以一个Slider为数据源,它的滑块可以从Value=0滑到Value=100;同时,我们以一个TextBox为数据目标,并通过Validation限制它只能将20到35之间的数据传回数据源。现实当中恐怕很少有这么干的,我们这个例子只是为了说明校验的使用方法:)
若要创建一个自定义的校验条件,需要声明一个类,并让这个类派生自ValidationRule类。ValidationRule只有一个名为Validate的方法需要我们实现,这个方法的返回值是一个ValidationResult类型的实例——这个实例携带着两个信息:
- bool类型的IsValid属性告诉Binding回传的数据是否合法
- object类型(一般是存储一个string)的ErrorContent属性告诉Binding一些信息,比如当前是进行什么操作而出现的校验错误等等,一般我会把这些信息写进Log文件里
实现好的类是这样的:
- public class MyValidationRule : ValidationRule
- {
- public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
- {
- double d = 0.0;
- if (double.TryParse((string)value, out d) && d >= 20 && d <= 35)
- {
- return new ValidationResult(true, "OK");
- }
- else
- {
- return new ValidationResult(false, "Error");
- }
- }
- }
在代码里这样使用它:
- Binding binding = new Binding("Value");
- binding.Source = slider1;
- binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
- binding.ValidationRules.Add(new MyValidationRule()); // 加载校验条件
- textBox1.SetBinding(TextBox.TextProperty, binding);
[WPF]Binding的Converter和Validator的更多相关文章
- WPF binding 参考
Introduction This is an article on WPF Binding Cheat Sheet. Some of the Binding won't work for Silve ...
- WPF Binding值转换器ValueConverter使用简介(二)-IMultiValueConverter
注: 需要继承IMultiValueConverter接口,接口使用和IValueConverter逻辑相同. 一.MultiBinding+Converter 多值绑定及多值转换实例 当纵向流量大于 ...
- WPF Binding值转换器ValueConverter使用简介(一)
WPF.Silverlight及Windows Phone程序开发中往往需要将绑定的数据进行特定转换,比如DateTime类型的时间转换为yyyyMMdd的日期,再如有一个值是根据另外多组值的不同而异 ...
- WPF Binding
winform有binding, WPF也有binding,区别在哪呢?这里暂时不提.以前也检查接触WPF binding, 但为什么过段时间就忘记了呢? 可能主要原因自己的知识体系不够完善吧,下面我 ...
- WPF入门教程系列(二) 深入剖析WPF Binding的使用方法
WPF入门教程系列(二) 深入剖析WPF Binding的使用方法 同一个对象(特指System.Windows.DependencyObject的子类)的同一种属性(特指DependencyProp ...
- WPF Binding Mode,UpdateSourceTrigger
WPF 绑定模式(mode) 枚举值有5个1:OneWay(源变就更新目标属性)2:TwoWay(源变就更新目标并且目标变就更新源)3:OneTime(只根据源来设置目标,以后都不会变)4:OneWa ...
- WPF Binding ElementName方式无效的解决方法--x:Reference绑定
原文:WPF Binding ElementName方式无效的解决方法--x:Reference绑定 需求: 背景:Grid的有一个TextBlock name:T1和一个ListBox,ListBo ...
- WPF的DataGrid的某个列绑定数据的三种方法(Binding、Converter、DataTrigger)
最近在使用WPF的时候,遇到某个列的值需要根据内容不同进行转换显示的需求.尝试了一下,大概有三种方式可以实现: 1.传统的Binding方法,后台构造好数据,绑定就行. 2.转换器方法(Convert ...
- C# wpf中关于binding的converter无效的情况
最近碰到bingding设置了convert转换无效的问题.困扰了我好久.这里记录分析一下. 先说下现象 我把TextBox的text属性 绑定到了对应的 convert.代码如下 希望吧pd_no ...
随机推荐
- Spring2.5学习3.3_@Autowire注解实现手动装配
@Autowired默认按类型装配,假设我在personDao 字段上加了@Autowired注解,那么就会默认取personDao 字段的类型在Spring容器中寻找与这个类型匹配的bean,寻找到 ...
- XenCenter注册码一年申请
http://deliver.citrix.com/go/citrix/xenserver_activation?transactionID=2f65d2f134bf485d871291a566d67 ...
- 纯后端尝试写一个前端slide插件
概述 由于项目组前端人员缺失,又赶上需要在手机端做一个slide效果的页面,所以只能自己硬着头皮上了,写的很简单,请大家不要笑话,只是拿出来分享下,大家先看下完成后的效果,如下: 过程 看了效果图是不 ...
- MFC 对话框中动态创建N级菜单以及响应事件
创建一个基于对话框的工程,工程名为CreateMenu 为该对话框增加一个文件菜单项和测试菜单项,如下图所示 测试菜单项至少要有一个子菜单项 在对话框属性中关联该菜单 在resource.h中增加 ...
- 一劳永逸解决UAC问题(修改QMAKE_LFLAGS_EXE的设置)
如果你的程序跑在一个开启了UAC保护的系统中,而你的程序又没有"盾牌"的话,程序总是会受到各种阻挠的,比如读写文件,写注册表等. 有了"盾牌"的话就不会出现一些 ...
- golang使用pprof检查goroutine泄露
有一段时间,我们的推送服务socket占用非常不正常,我们自己统计的同一时候在线就10w的用户,可是占用的socket居然达到30w,然后查看goroutine的数量,发现已经60w+. 每一个用户占 ...
- PHP中抽象类与接口的应用场景
<?php /*** ====笔记部分==== 接口的具体语法: 0:以人类为, class Human 是人的草图 而接口 是零件 可以用多种零件组合出一种新特种来. 1: 如上,接口本身即是 ...
- hdu 4039 The Social Network
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4039 题目分类:字符串+bfs 题意:给一个人际关系图,根据关系图,给一个人推荐一个人认识 题目分析: ...
- JS的类型比较与转换图
完整比较图:红色:===橙色:==黄色:<= 和 >= 同时成立,== 不成立蓝色:只有 >=绿色:只有 <= https://www.zhihu.com/question/3 ...
- WebService-03-使用CXF开发服务端和客户端
写在前面的话 前面两节说了使用Java提供的包开发服务端和客户端,现在使用CXF来开发,CXF提供了两个类发而服务,一个是ServerFactoryBean,另一个是JaxWsServerFactor ...