今天来学习一下WPF的一些重要概念,后面的学习课程非常依赖对这课的理解。
1、逻辑树与可视树
在WPF中,用户界面由一个对象树构建而成,这棵树叫逻辑树
上述XAML内容实际上就是由Window、Stack Panel、Label等构成,大家可以看到,Window是根元素,StackPanel是Window的子元素,Label是StackPanel的子元素
在XAML中,所有的元素都存在父子关系,形成了一棵树,整个界面就是由这些对象树构建而成,这棵树叫做逻辑树。逻辑树概念很直观,WPF的属性、事件、资源等都有与逻辑树相关联的行为。
与逻辑树类似的是可视树,可视树是逻辑树的扩展,如下图所示:
2、依赖属性
WPF引入了一个新的属性类型叫作依赖属性,整个WPF平台中都会使用该属性,它主要用来实现样式化、自动数据绑定、动画等,该属性最大的特点是其内建的传递变更通知(change notification)的能力,它完全由WPF API实现,融入了WPF架构中。
添加这样的智能给属性,其动力在于能够声名标记中直接启用富功能。下面深入分析依赖属性在.net属性上赋值的一些方式
a、变更通知
b、属性值继承
c、对多提供程序支持
一个标准依赖属性实现
变更通知:只要依赖属性值发生变化,WPF会根据元数据(MetaData)会触发一系列操作。
依赖属性是静态变量来实现,所以可以大幅降低内存的占用,多数实例都公用该变量,以Button为例来看看依赖属性变更通知原理:
上述代码是当鼠标移动到Button上时,将前景色修改成Blue,鼠标移开时,恢复本来颜色。
WPF除了属性触发器,还有数据触发器和事件触发器,后面会详细说到其他两个触发器。
属性继承:属性值的继承并不是指面向对象编程中的继承,而是指属性值自顶向下沿着元素树进行传递。
下面以Window中FontSize为例子来说明这个继承关系。首先设置窗口FontSize属性值为20和30,窗口中其他元素的字体是否会变化:
效果:
可以明显看到,窗口中所有的元素的字体大小发生了变化,修改窗口的FontSize实际上是修改元素树的顶层节点属性,因此会影像所有的子元素。如果显示设置子元素的属性,子元素的属性会覆盖父元素的属性,当然并不是所有属性都存在继承行为,属性的继承有两种因素决定:
a)依赖属性会通过传递FrameworkPropertyMetadataOption.Inherits和DependencyProperty.Register方法来完成继承。
对多个程序提供的支持:依赖属性值管道
附加属性:附加属性是依赖属性特殊形式
3、路由事件
路由事件是专门设计用于在元素树中使用的事件,当路由事件触发后,它可以向上或者向下遍历可视树和和逻辑树
路由事件的实现也是基于WPF API ,下面看看Button的Click事件是如何实现的:
路由策略和事件处理
事件注册完成后,每个路由事件将选择3个路由策略中的一个(Tunneling管道传递 Bubbling冒泡 Direct直接)
管道传递是事件首先在根元素上触发,然后每个元素沿逻辑树进行传递直到源元素。
冒泡:事件首先在源元素上触发,然后每个元素向上传递,直到根元素。
直接:事件只在源元素上触发。
示例:
在Window上实现RightButtonDown事件,在事件中获取Window上控件的相关信息,看事件路由到底是个什么东东。
当邮件点击窗口上子元素时,子元素会被加上边框,而且相关的信息会写到窗口的标题上
4、命令
命令表示的是那些与界面分离的动作,最标准的命令:复制、粘贴、剪切等命令,WPF命令有三种特性:
WPF定了许多内建命令
命令自动支持输入手势
有些WPF控件有一些与不同命令关联的内建行为。
内建命令:
WPF命令实现了ICommand接口,WPF已经实现的内建命令
在Button上实现命令
除了能够在后台编码实现内建命令的响应,也可以在XAML中设置,在后台实现HelpCanExcute和HelpExecuted路由事件。
后台实现:
5、漫游类层次
WPF类有深度继承层次,想吧不同的类和它们之间的关系搞清楚很困难,但是必须把WPF内部工作机制的基础搞清楚,下面有张图,是WPF核心类的关系
类的说明: