1.狂妄的WPF
相对传统的Windows图形编程,需要做很多复杂的工作,引用许多不同的API。例如:WinForm(带控件表单)、GDI+(2D图形)、DirectX API(3D图形)以及流媒体和流文档等,都需要不同的API来构建应用程序。
WPF就是看着上面的操作复杂和不爽,自己决定做老大,想用DirectX技术涵盖一切,于是想要将上述的东西全部融合到自身,减少复杂度,让编程变得爽起来的技术。
而不可否认的是,WPF虽然很狂妄,但是这种技术里面还是有不少的可圈可点的东西。而支持WPF狂妄的资本,则就是和它后台代码可以前后分离的XAML技术。下面用30分钟时间说一下XAML。
2.什么是XAML
一个界面程序的核心,无疑就是界面和后台代码,而xaml就是微软为构建应用程序界面而创建的一种描述性语言,也就是说,这东西是搞界面的。
先上一段xaml代码:
<Window x:Class='MyXaml.Window1' xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' Title='MyXaml' > <Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <TextBlock Grid.Column='0' Grid.Row='0' FontWeight='Bold' Text='姓名:'/> <TextBlock Grid.Column='0' Grid.Row='1' FontWeight='Bold'>性别:</TextBlock> <TextBlock Grid.Column='0' Grid.Row='2' FontWeight='Bold' Text='年龄'></TextBlock> <TextBox Grid.Column='1' Grid.Row='0' FontWeight='Bold' /> <TextBox Grid.Column='1' Grid.Row='1' FontWeight='Bold'/> <TextBox Grid.Column='1' Grid.Row='2' FontWeight='Bold'/> </Grid> </Window>
上述xaml是我设计了一个三行两列的界面,运行之后显示如下:
在此,我没有写一行c#代码,但是它竟然可以运行,所以也可以说它也是一种编程语言。只不过它更关注界面上面的东西而已。
那么它的运行是如何产生的?下面看几个东西:
x:Class='MyXaml.Window1' ——利用class特性指定c#类名(后台c#代码)
xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml——这表示利用x代替XAML的命名空间。用于包含特定的关键字和System.Windows.Markup中类型的子集。
xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation——另一个命名空间。映射诸多wpf.net命名空间(system.windows.xxx,是个一对多的映射,主要封装了三个程序集中,WindowsBase.dll、Presentation.dll和PresentationFramework.dll)
2.1 启动
程序启动的地方,其实是在程序的App.xaml文件里面:
<Application x:Class='MyXaml.App' xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' StartupUri='Window1.xaml'> <Application.Resources> </Application.Resources> </Application>
看下面这句:
StartupUri='Window1.xaml'
这个就是程序的入口点,运行程序之后,我们就将window1显示在了显示屏上。
3.XAML语法概述
上述xaml中,显示的一个核心布局就是以下这些代码:
<Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <TextBlock Grid.Column='0' Grid.Row='0' FontWeight='Bold' Text='姓名:'/> <TextBlock Grid.Column='0' Grid.Row='1' FontWeight='Bold'>性别:</TextBlock> <TextBlock Grid.Column='0' Grid.Row='2' FontWeight='Bold' Text='年龄'></TextBlock> <TextBox Grid.Column='1' Grid.Row='0' FontWeight='Bold' /> <TextBox Grid.Column='1' Grid.Row='1' FontWeight='Bold'/> <TextBox Grid.Column='1' Grid.Row='2' FontWeight='Bold'/> </Grid>
1、看Grid控件,这个在wpf中是一个布局控件,就跟将窗体设置单元格差不过,可以依据它的row和column属性来设置行和列。上述设置了一个三行两列的布局。
2、看TextBlock和TextBox控件,这些都是一些显示控件,一个显示条和一个文本框,wpf中除此之外,还有许多的控件。
首先需要再确认的一点,那就是在C#中一切皆对象。如此一来,也就好理解了。
在XAML中的这些形形色色的控件其实就是一个个的类,我们应用了他们就相当于是应用了一个个的对象,而他们之中定义的一些width、height等属性,就是这些类中封装的一些属性字段。
当然,像上面TextBox和TextBlock中的Grid.Column='1' Grid.Row='2'等属性,其实并不属于这两个类中的属性和字段。
而使得他们具备这样属性的,无疑就是外面的Grid布局控件赋予的,而在WPF中这样的功能实现叫做附加属性,是依赖属性的一个特殊的用法。关于依赖属性,在以后会详细的讨论。
第一个总结
WPF的XAML语法其实可以理解成另外一种形式的编程语言,其语法表现形式和XML类似,但是更严谨和更要求准确性。
XAML主要包括布局和控件,以此来构建各种形态的应用程序,除此之外,其中还有许多新的强大的东西,使得它更灵活和方便,例如依赖属性。
3.1 布局
WPF中的布局常用的主要包括五种:Canvas、Grid、StackPanel、DockPanel和WrapPanel。下面分别说一下这五种布局控件的使用。
1、 Canvas
要说Canvas,先看以下的xaml代码:
<Canvas> <Button Content='btn1' Margin='10'/> <Button Content='btn2' Margin='10'/> </Canvas>
然后,查看在画布Canvas上面生成的画面,情况如下:
为什么不显示btn1?因为两个button重叠了起来,只显示最上面的控件(越接近结束标签 </Canvas>的控件,如果两个button的位置颠倒一下,显现出来的就是btn1).