《桂林电子科技大学学生学习深入浅出WPF3数据的绿色通道Binding(上) (2)》由会员分享,可在线阅读,更多相关《桂林电子科技大学学生学习深入浅出WPF3数据的绿色通道Binding(上) (2)(10页珍藏版)》请在金锄头文库上搜索。
1、深入浅出 WPF 第三辑 数据的绿色通道,Binding(上) 小序: 啊哦,实在是不好意思,最近实在是太忙了,忙的原因也非常简单自己的技术太差了,还有很多东西要学呀。门里门外,发现专业程序员非常重要的一项技能是读别人写的代码,这项技能甚至比自己写代码更重要。Anstinus 同学就是读代码的高手,我写的代码他看两眼就知道怎么回事了,并且能够立刻修改,而他的代码我读了好几天还不知道是怎么回事儿呢。 因此,毫不夸张地说,从本篇文章起接下来的几篇文章几乎可以说是 WPF 的核心内容,非常重要。这几篇文章分别介绍了Binding、Dependency Property、Routed Event &
2、Command 等内容。精彩不断,敬请关注!正文:在学习新东西的时候,人们总是习惯拿它与自己已经了解的旧有知识去做比较,这样才掌握得快、记忆深刻。所以,经常有朋友问我:“WPF 与 Windows Form 最大的区别是什么?请用最简短的话告诉我。”OK,这个问题问的非常好看上去 WPF 与 WinForm 最大的区别像是前面讲的那个 XAML 语言,但 XAML 只是个表层现象,WPF 真正引人入胜、使之与 WinForm 泾渭分明的特点就是“数据驱动界面”。围绕着这个核心,WPF 准备了很多概念相当前卫的技术,其中包括为界面准备的 XAML、为底层数据准备的 Dependency Prop
3、erty 和为消息传递准备的 Routed Event & Command。“数据驱动界面” ,听起来有点抽象。用白话解释(中文白话似乎总也上不了台面、更不能往书里写,而老外的书里却可以白话连篇)就是数据是底层、是心脏,数据变了作为表层的 UI 就会跟着变、将数据展现给用户;如果用户修改了 UI 元素上的值,相当于透过 UI元素直接修改了底层的数据;数据处于核心地位,UI 处于从属地位。这样一来,数据是程序的发动机(驱动者)、UI 成了几乎不包含任何逻辑专供用户观察数据和修改数据的“窗口” (被驱动者)。顺便插一句,如果你是一位 WinForm 程序员,“ 数据驱动界面”一开始会让你感觉不太习
4、惯。比如,在 WinForm 编程时,如果想对ListBox 里的 Item 排序,我们会直接去排列这些 Item,也就是针对界面进行操作,这在 WPF 里就行不通了实际上,在 WPF 里因为界面完全是由数据决定的(甚至包括界面元素的排序),所以,我们只需要将底层数据排序,作为界面的 Items 也就在数据的驱动下乖乖地排好序了。那么,数据是怎样从底层传递到界面的呢?我们今天的主角,Binding 同学,就要登场啦!深入浅出话 BindingBinding 同学最近很不开心,是因为它的中文名字“很暴力” 绑定。我猜,最早的译者也没什么标准可遵循,大概是用了谐音吧!这一谐音不要紧,搞的中国程序员
5、就有点摸不清头脑了。“绑” 是捆绑的意思,再加上一个“ 定”字,颇多了几分“绑在一起、牢不可分”的感觉。而实际呢?Binding 却是个地地道道的松耦合的关系!依在下拙见,Binding 译为“关联”是再合适不过了。在英语词典里,也的确有这一词条。关联吗,无需多讲,人人都知道是“之间有些关系”的意思。Data Binding 也就不应该再叫“数据绑定” 了,应该称为“数据关联” ,意思是说,在数据和界面(或其他数据)之间具有某些关系和联动。具体到 WPF 中,Binding 又是怎样一种关系和联动呢?就像我们的大标题一样 Binding 就是数据的“绿色通道”。“绿色通道”代表着“直接” 和“
6、快速”,Binding 就是这样。让我们分享一个有趣的例子,请看下面的截图:这里是两个 TextBox 和一个 Slider 组成的 UI,现在客户的需求是当 Slider 的滑块移动时,上面那个 TextBox 里显示 Slider 的Value;反过来,当在上面那个 TextBox 里输入合适的值后,鼠标焦点移开后, Slider 的滑块也要滑到相应的位置上去。站在一个 WinForm 程序员的角度去考虑,他会做这样几件事情:1. 响应 slider1 的 ValueChanged 事件,在事件处理函数中让 textBox1 显示 slider1 的 Value 2. 响应 textBox
7、1 的 LostFocus 事件,把 textBox1 的 Text 转换成数值,并赋值给 slider1 注意了!这就是典型的“非数据驱动界面”的思想。为什么呢?当我们响应 slider1 的 ValueChanged 事件时,我们要的是 slider1 的 Value 这个值,这时候,slider1 处于核心地位、是数据的“源”(Source);当我们响应 textBox1 的 LostFocus 事件时,我们需要的是它的 Text 属性值,这时候,textBox1 又成了数据的 source。也就是说,在这种处理方法中,数据没有固定的“源” ,两个 UI 元素是对等的、不存在谁从属于谁的
8、问题。换句话说:它们之间是“ 就事论事”,并没有什么“ 关联” 。接下来,让我们体验一下“绿色通道”的快捷!上述例子的 XAML 源代码如下:view plaincopy to clipboardprint?1. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 剔除那些花里呼哨的装饰品后,最重要的只有下面 3 行(而实际上第 2 行那个 textBox2 只是为了让鼠标的焦点有个去处):view plaincopy to clipboardprint?1. 2. 3. 4. 5. 然后,我只需在第 1 行代码上做一个小小的修改,就能完成 WinForm 中
9、需要用两个事件响应、十多行代码才能完成的事情:view plaincopy to clipboardprint?1. 2. 3. 4. 5. 细心的你,一定一眼就看到只多了这样一句话:Text=Binding ElementName=slider1, Path=Value这句话的意思是说:Hi,textBox1,从此以后,你的 Text 属性值就与 slider1 这个 UI 元素的 Value 属性值关联上了,Value 变的时候你的 Text 也要跟着变。这时候的效果是你拖动 Slider 的滑块,textBox1 就会显示值(双精度,0 到 100 之间);你在 textBox1 里输入
10、一个 0 到 100 之间的数字,当把鼠标移动到 textBox2 里时,slider1 的滑块会跳到相应的值上去,如图:非常简单是不是?请注意,这里面可蕴含了“数据驱动界面” 的模型哦!在这里,我们始终把 slider1 的 Value 当成是数据源(Data Source),而 textBox1 则是用来显示和修改数据的窗口( Data Presenter)slider1 是核心,它的 Value 属性值将驱动 textBox1 的Text 进行改变;人为改变 textBox1 的 Text 属性值,也会被送回到 slider1 的 Value 属性值上去。是时候让我们了解 Data Bi
11、nding 的几个关键概念了 1. 数据源(Data Source,简称 Source):顾名思义,它是保有数据的实体、是数据的来源、源头。把谁当作数据源完全由程序员来决定只要你想把它当做数据核心来使用。它可以是一个 UI 元素、某个类的实例,也可以是一个集合(关于对集合的绑定,非常重要,专门用一篇文章来讨论之)。 2. 路径(Path):数据源作为一个实体可能保有着很多数据,你具体关注它的哪个数值呢?这个数值就是 Path。就上面的例子而言,slider1 是 Source,它拥有很多数据除了 Value 之外,还有 Width、Height 等,但都不是我们所关心的所以,我们把 Path
12、设为 Value。 3. 目标(Target):数据将传送到哪里去?这就是数据的目标了。上面这个例子中,textBox1 是数据的 Target。有一点需要格外注意:Target 一定是数据的接收者、被驱动者,但它不一定是数据的显示者也许它只是数据联动中的一环 后面我们给出了例子。 4. 关联(Binding): 数据源与目标之间的通道。正是这个通道,使 Source 与 Target 之间关联了起来、使数据能够(直接或间接地)驱动界面! 5. 设定关联(Set Binding):为 Target 指定 Binding,并将 Binding 指向 Target 的一个属性,完成数据的“端对端”
13、传输。 绿色通道上的“关卡” :话说眼看就要到奥运会了,北京的各大交通要道上也都加强了安检力度。微软同学也给 Binding 这条“绿色通道” 准备了几道很实用的“关卡”。这些 “关卡”的启闭与设置是通过 Binding 的属性来完成的。其中常用的有: 如果你想把“绿色通道”限制为“单行道”,那就设置 Binding 实例的 Mode 属性,它是一个 BindingMode 类型的枚举值,其中包含了 TwoWay、OneWay 和 OneWayToSource 几个值。上面这个例子中,默认地是 TwoWay,所以才会有双向的数据传递。 如果用户提出只要 textBox1 的文本改变 slide
14、r1 的滑块立刻响应,那就设置 Binding 的 UpdateSourceTrigger 属性。它是一个 UpdateSourceTrigger 类型枚举值,默认值是 UpdateSourceTrigger.LostFocus,所以才会在移走鼠标焦点的时候更新数据。如果把它设置为 UpdateSourceTrigger.PropertyChanged,那么 Target 被关联的属性只要一改变,就立刻传回给Source我们要做的仅仅是改了一个单词,而 WinForm 程序员这时候正头疼呢,因为他需要去把代码搬到另一个事件响应函数中去。 如果 Binding 两端的数据类型不一致怎么办?没关系
15、,你可以设置 Binding 的 Converter 属性,具体内容在下篇文章中讨论。 如果数据中有“易燃易爆”的不安全因素怎么办?OK ,可以设置 Binding 的 ValidationRules,为它加上一组“ 安检设施”(同样也在下篇文中讨论)。 在 C#代码中设置 BindingXAML 代码是如此简单,简单就那么一句话。这可不是吾等 C#程序员、刨根问底之徒可以善罢甘休的!形象地讲,Binding 就像一个盒子,盒子里装了一些机关用于过滤和控制数据,盒子两端各接着一根管子,管子是由管壳和管芯构成的,看上去就像下面的图: 当脑子里有了这样一个形象之后,遵循下面的步骤就 OK 了:1. Source:确定哪个对象作为数据源 2. Target:确定哪个对象作为目标 3. Binding:声明一个 Binding 实例 4. 把一根管子接到 Source 上并把管芯插在 Source 的 Path 上 5. 把另一根管子接到 Target 上并把管芯插在 Target 的联动属性上 如果有必要,可以在 3 与 4 之间设置 Binding 的“关卡” 们。其实,第 3 步之后的顺序不是固定的,只是这个步骤比较好记一概向右连接。所得结果看上去是这样:我猜你可能会问:“那个 D.P.是什么呀?”D.P.的全称是“