WPF 的内部世界(Binding)

2,573 阅读6分钟

目录

一、控件与布局

二、Binding基础

前言

“一桥飞架南北, 天堑变通途”

写于1956年,1957年武汉长江大桥建成, 称之为:一桥飞架南北,大堑变通途.它形象地描述武汉长江大桥的雄伟气势及其在我国南北交通方面发挥的重要作用。

哈哈,为什么要说这么一句无头理的话呢?

Binding一词,第一反应给我们以“绑定”的涵义。错了错了~~

Binding就好像一个“桥梁”

额……对没错,就是桥梁,Bind 一词在做动词时,实际上具有关联的含义。

也就是说Binding更注重表达它是一种像桥梁一样的关联关系

我们通过Binding完成UI层与逻辑层的数据交互, 当逻辑层的属性发生变动时,会通知Binding,当Binding知道是哪个属性变动后,通知给UI端相关联的控件,完成相应动作。

属性是怎么发出通知的?

属性

快捷键“propf”

 private int myVar;

 public int MyProperty
 {
     get { return myVar; }
     set { myVar = value; }
 }

属性是没有办法发出通知的,比如我我把值改为了3,它是不会去通知别人说:“看!我变成小3了!!”。

它要是会通知的话,那真是“见鬼了!”。

让属性说话的魔法(INotifyPropertyChanged)

我们是伟大的程序猿,想让属性说话还不简单,我们有魔法!

INotifyPropertyChanged 接口

译为“属性变化时通告”

我们创建一个Student类实现这个接口。

发现它实现了一个事件“PropertyChanged”。

“说话的能力”PropertyChanged

接口默认实现了一个事件,

这个事件怎么用呢?在哪里执行呢?

  • 我们知道是当“属性的值发生改变时去通知”。
  • 在属性里赋值为set方法 ,所以我们的事件在set方法体里实行。

我这里用了事件执行的一个语法糖,意思是 “不为空时就执行事件(?.Invoke())”。

当是,你可能更常见的是这种

PropertyChanged的参数

第一个参数也就是触发这个事件的对象(this),第二个参数实际上告诉是哪个属性发生了变化(new PropertyChangedEventArgs(propName)),所以是个字符串,表示当前属性的名称。

好吧!!属性有了能力呢,那么是怎么Binding(关联)的呢?

C#里的Binding

一、首先,我们在页面放置一个文本框和一个按钮,要实现点击按钮时:文本框的内容随着Binding的属性的值改变而发生改变。

给文本的Name赋值为“txt1”,给按钮添加一个点击事件(先像winform那样,找到控件的属性-》事件里去添加)

二、在窗体的后台代码里,初始化,绑定Binding

没错,我们并没有去操作什么,只是让学生的姓名变化,文本框就自动变化了,这就是Binding。

在这里我们衍生出几个知识点:

“问渠哪得清如许,为有源头活水来”

设问:这“半亩方塘”为什么这么清澈呢?并自答:因为有这源头活水不断地补充进来,才使得它这么清澈。——朱熹的《观书有感》

就好像我们的程序为什么这么有活力呢,正是因为有好的源头(水源),还有路径(水流的道路)。

1、Source(数据源)

Binding对数据源的要求并不是那么苛刻,只要它是一个对象,并且通过属性公开自己的数据(set;get;),它就能作为Binding的源。

就好像我们把Student的当作数据源,Student的通过公开属性(Name)让我们拿到信息。

2、Path(路径)

数据公开了,我们怎么拿到呢?

我们需要通往它的道路(Path),Binding的Path是一个PropertyPath类型,参数是一个string。也就是属性的名称(Name)。

我们把属性的名称来当作访问的路径。

3、Binding 怎么和控件关联

我们已经实例化好了一个Binding,并且设置了Source和Path。现在,我们需要将它与文本框关联。

BindingExpressionBase.SetBinding(DependencyObject target, DependencyProperty dp, BindingBase binding)

参数:

  • target:绑定的绑定目标。
  • dp:绑定的目标属性。
  • binding: 描述绑定的 System.Windows.Data.BindingBase 对象。

三、Binding的简写方法

1、this.name.SetBinding()

2、new Binding(){}

xaml里的Binding

一、构造函数改变一下

我们这里使用文本框的DataContext赋值数据源,而不是用Binding的Source.

因为在xaml代码里去binding一个Source是很麻烦的事情。而且,一般只有静态资源,或者是以控件的数值为数据源时,我们才在xaml代码里去BindingSource(这个轮到后面展示)

DataContext数据上下文

  • 当一个Binding没有Source时,会发生什么了?它会把当前对象的DataContext作为数据源。
  • DataContext属性定义在FrameworkElement类里,这个类是WPF控件的基类,这就意味着,所有控件都有这个属性。
  • 如果当前对像的DataContext为空,它就会像它的父容器”借“一下。

所以也可以写成这样

二、编写xaml代码

三、XAML中Binding写法的解释

  • Text=“{Binding Path=Name }”
  • 解读:并不是为Text赋了一个Binding的值。
  • 应该是为TextBox的属性Text关联(Binding)了一个数据源,可以把这看成一个 Binding的构造函数,相当于初始化Binding

还记得一开始的写法嘛

Binding静态资源和控件

1、关联静态资源

Resource

每个控件都有一个 Resource属性,我们可以在里面存放资源,方便访问。

在这里我们实例化了一个Student,并且设定了一个key=“student”。

Source={StaticResource student}

通过StaticResource访问静态资源,通过key来确定关联哪个数据源。

2、关联控件

我们来实现一个效果,当滑动进度条时,文本显示滑动的值,文本框输入值,进度条滑动到合适的位置。

(方法一)放置俩个控件,在C#里关联控件

我们会发现只有当文本框的值失去焦点时,进度条的显示才会变化。我们来设置一下: UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged(当值发生变化时就触发)

(方法二)放置俩个控件,在xaml里关联控件

就是这么简单,我们这里使用的时elementname来绑定是哪个控件,你看Binding的样式,是不是特别像构造函数初始化

BindingPath的“/”用法

当我们数据源的一个属性是一个集合时,我们需要集合里的子元素。怎么去Path指定呢?

我们在创建一个班级类,班级类有一个Name属性,还有一个Student集合,代表有多个学生。

如果数据源的属性是一个集合,要把集合中的子元素当作Path,使用多斜线的语法,一路“斜下去”。

结尾

呼,Binding的用法实在太多了,剩下的数据校验和数据转换,下期在做,当然我总结的可能很懒散,但是我是尽量再用白话文来解释。一定要多动手尝试,你就会发现Binding的乐趣所在。

“你不能拥有的,别人替你去拥有”