上一篇我们介绍了WPF基本的知识。并且介绍了WPF与winform传统的cs桌面应用编程模式上的变化,这篇,我们将会对WPF的一些基础的知识做一个简单的介绍,关于这些基础知识更深入的应用则在后续的篇幅中大幅度的应用。
Xaml(Extensible Application Markup Language) 可扩展应用程序标记语言,该语言基于xml实现的进行了相应的扩展。该语言很容易进行扩展,有点类似B/S编程中的代码后置,前端是HTML,后台是业务逻辑和相关处理代码。
还有一点是我们反复强调的,XAML并不是HTML。尽管XAML在元素的声明、程序样式的设置和指定事件处理程序上都和HTML非常类似,但是XAML是基于XML的,它是WPF的外在表现形式。而HTML主是一种标记语言,仅仅是用来为浏览器呈现页面内容。XAML除了用来呈现信息和请求用户输入等基本的功能外,它还包含了一些高级的特性,例如它提供了对动画和3D众多方面的支持。
xaml语言,微软提供了可视化的设计工具blend。基于blend创建的的界面模型及效果,都可以存储或者转换为xaml格式的代码,这样就可以大大的提高了团队中的设计人员和开发人员之间的协作,减少了设计人员原型效果,开发人员无法实现,设计人员可以自行设计后,转换为xaml代码。
关于xaml更多的内容,可以参考维基百科或百度知道。
相关的简单说明如下:
对于熟悉XML的同仁,应该没有什么难理解的。
我们先来看看MSDN给出的定义:
功能定义:路由事件是一种可以针对元素树中的多个侦听器(而不是仅针对引发该事件的对象)调用处理程序的事件。
实现定义:路由事件是一个 CLR 事件,可以由 RoutedEvent 类的实例提供支持并由 Windows Presentation Foundation (WPF) 事件系统来处理。
我们来解释下MSDN给出的定义:
1、传统方式:
对应的xaml代码和后台代码如下:
后台对于的处理如下:
当然采用如下的方式也是可行的。
后台代码修改为:
2、WPF的路由方式:
路由事件使用以下三个路由策略之一:
冒泡:针对事件源调用事件处理程序。路由事件随后会路由到后续的父元素,直到到达元素树的根。大多数路由事件都使用冒泡路由策略。冒泡路由事件通常用来报告来自不同控件或其他 UI 元素的输入或状态变化。
直接:只有源元素本身才有机会调用处理程序以进行响应。这与 Windows 窗体用于事件的“路由”相似。但是,与标准 CLR 事件不同的是,直接路由事件支持类处理(类处理将在下一节中介绍)而且可以由 EventSetter 和 EventTrigger 使用。
隧道:最初将在元素树的根处调用事件处理程序。随后,路由事件将朝着路由事件的源节点元素(即引发路由事件的元素)方向,沿路由线路传播到后续的子元素。在合成控件的过程中通常会使用或处理隧道路由事件,这样,就可以有意地禁止显示复合部件中的事件,或者将其替换为特定于整个控件的事件。在 WPF 中提供的输入事件通常是以隧道/冒泡对实现的。隧道事件有时又称作 Preview 事件,这是由隧道/冒泡对所使用的命名约定决定的。
在传统的方式中,我们必须对每个事件源进行事件处理绑定,如果我们新增加新的对象或者新的事件源,那么我们还需要添加新的绑定。而这一切在WPF,都被统一处理和考虑了,下面,我们以冒泡为例来简单说明。
冒泡的顺序
修改后台代码如下:
关于逻辑树与可视化树,我们这里解释下:
逻辑树:简单来说,就是我们从界面上来看 界面的可视化基本组成部分,这就构成了窗口的一个逻辑树。逻辑树始终存在于WPF的UI中,不管UI是用XAML编写还是用代码编写。WPF的每个方面(属性、事件、资源等等)都是依赖于逻辑树的
可视树:可视树基本上是逻辑树的一种扩展。逻辑树的每个结点都被分解为它们的核心视觉组件。逻辑树的结点对我们而言基本是一个黑盒。而可视树不同,它暴露了视觉的实现细节。下面是Visual Tree结构就表示了上面四行XAML代码的视觉树结构。
可视树,将界面组成的所有对象本身的内容进行了解析,例如button 按钮,他的内容,是有contentpresenter和textblock构成。
关于逻辑树和可视树的更多介绍,可参考MSDN的介绍。
我这里给出简单的获取逻辑树和可视树的代码:
都上WPF本身提供了一些方法。采用递归的方式。
我们接着上面的关于查看事件源的地方:
经过上面我们看到了,默认情况下,WPF的事件是采用冒泡的方式进行事件的传递的,那么我们如何采用其他的二种策略呢?
我们再来看下隧道事件,隧道事件的顺序如下:引用MSDN中的解释图:
输入事件的冒泡和隧道
事件的处理顺序如下所示:
针对根元素处理 PreviewMouseDown(隧道)。
针对中间元素 1 处理 PreviewMouseDown(隧道)。
针对源元素 2 处理 PreviewMouseDown(隧道)。
针对源元素 2 处理 MouseDown(冒泡)。
针对中间元素 1 处理 MouseDown(冒泡)。
针对根元素处理 MouseDown(冒泡)。
我们来验证下,我们以此处理所有的preview事件,看看是不是按照上面介绍的方式去处理的。
对应的后台代码如下:
运行,后查看输出结果:
与我们预期的一致。关于更多的路由事件,我们后面通过单独的章节来说明。
系统默认提供的基础控件:
有些由于自己也没有进行深入的使用,可能就不会介绍太详细。
关于控件的基本使用,会在后续进行深入的讨论和演示。
DependencyProperty(依赖属性):Windows Presentation Foundation (WPF) 提供了一组服务,这些服务可用于扩展公共语言运行时 (CLR) 属性的功能,这些服务通常统称为 WPF 属性系统。由 WPF 属性系统支持的属性称为依赖项属性。
WPF界面控件中的属性,都可以称作是依赖属性,通过依赖属性,我们能够实现viewModel与界面元素属性之间进行绑定。
依赖属性与我们平时说的属性有区别的。
1、传统的属性
这没啥好说的,就是我们针对对象进行了封装。
假设,我们有一个类,有很多的属性,而且,又被多个对象继承,我们知道继承的特性,那么肯定会有很多的属性,本身我们可能基本不适用,那么该属性,还是会被创建的时候实例化,那么有没有什么办法,我们减少这样的开销呢?WPF针对这样的情况提出了依赖属性的概念。
2、依赖属性:
查看其基本的声明和定义:在注释中描述:通过方法设置的属性,数据绑定,动画,样式等。
依赖属性就是自己自己没有值,通过Binding从数据源获得值,就是依赖在别人身上,拥有依赖属性的对象称为依赖对象。
我们来看看WPF控件的基本继承链
关于依赖属性的声明和更详细的内容,我们在后续的单独的章节中有更详尽的介绍。
几种应用依赖属性的场景:
后面的章节,我们会结合具体的案例,来说明如何使用依赖属性。
有了依赖属性后,我们就可以实现界面的绑定机制了,就会比较容易处理了,既然实现界面的绑定的话,就需要实现接口:INotifyPropertyChanged 实现了该接口的属性,就可以通过绑定的方式,将属性绑定到控件的属性上
下面给出一个简单的绑定的例子
我们来查看下,xaml代码和后台的代码,我们会发现,我们没有对文本框设置过任何的值,而是通过绑定来实现的赋值操作.
1、xaml代码如下:
2、后台代码中,我们并没有设置任何的关于Textbox的赋值或者设置值的代码和操作:
3、我们接着看看TestViewModel的实现和要注意的事项:
注意这里的绑定属性,必须是public,并且 事件通知的名称必须与属性名称一致。
BaseViewModel的代码:
后面关于我们进行MVVM编程时,还会使用这部分的内容。
WPF中的资源,包含的内容比较多,样式,图片,视频,动画等,都可以称作资源。资源,我们一般可以再一个应用程序范围内容定义公共资源,也可以在一个页面内定义资源。
我们平时看到有很多的软件,有很多的主题,在WPF中就可以通过定义样式来实现,这点有点类似web上的样式表。
我们可以再运行期动态的修改样式表,达到修改界面的目标。
下面,我们样式下,如何使用资源,简单的介绍资源的几种使用方式,关于更多的资源的介绍,在后续单独的章节中介绍。
1、添加样式文件
添加样式内容如下:
将样式文件添加到App中
运行查看效果:
如果,我们不想使用默认的样式应该怎么办
我们只要自己设置了属性值后,他就不会使用样式表中定义的属性值:
例如,我们只要设置 宽160,高30,字体大小10 然后再次运行看看效果
同样,如果我们只需要在当前的页面,应用当前的样式,那么我们就不要再App中加入样式文件,二是把代码移动到当前的页面中:
上面就是对资源文件的简单介绍,后续会对样式的设置和应用等结合具体的例子进行更深入的介绍。
1、Grid的布局
这个就没啥特别好说的,其实,基本上复杂的布局,都需要用到Grid。
主要就是对行和列进行进行设置和定义。
1、行表格
列表格:
包含行和列的表格
2、StackPanel
垂直方向:
3、DockPanel
4、WarpPanel
本文涉及到的内容比较多,但是讲述的内容,都不深入,大家对基本的用法有一定的了解即可,后续的章节,将会更深入的介绍,并且结合实际项目中的心得体会进行总结和分享。