- [1. 最简单的WPF应用](#1. 最简单的WPF应用)
- [1.1. App.config](#1.1. App.config)
- [1.2. App.xaml 和 App.xaml.cs](#1.2. App.xaml 和 App.xaml.cs)
- [1.3. MainWindow.xaml 和 MainWindow.xaml.cs](#1.3. MainWindow.xaml 和 MainWindow.xaml.cs)
- [2. 正式开始分析](#2. 正式开始分析)
- [2.1. 声明即定义](#2.1. 声明即定义)
- [2.2. 命名空间](#2.2. 命名空间)
- [2.2.1. xaml的Property和Attribute](#2.2.1. xaml的Property和Attribute)
- [2.2.2. xaml中命名空间](#2.2.2. xaml中命名空间)
- [2.2.3. partial关键字](#2.2.3. partial关键字)
学习WPF,肯定要先学习XAML语法,说实话,XAML这种语言一点也不难。如果把XML看成是"父类",那么XAML就是XML的一个派生类了,所以XML的概念在XAML中是通用的。
What?你不了解XML?没关系,反正我们是从头开始!
针对XAML文件,是可以进行"所见即所得"的可视化设计的。你在XAML代码上做的修改,只要是合乎语法的,那么在设计器里就会立刻反映出来(有时候需要刷新一下)。
如果你发现设计器里显示不出来了,那一定是XAML语句出了问题,最好想办法修正它。不然的话,在设计器里都看不到效果、只能运行起来看,这还是不是可视化编程了。。
1. 最简单的WPF应用
新建WPF窗体应用,默认有以下几个文件:
1.1. App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
</configuration>
其实就是一个xml文件,定义了.NET Framework的版本信息
1.2. App.xaml 和 App.xaml.cs
一个是UI元素代码,一个是后台交互逻辑代码,具体分析后面我们在看。
<Application x:Class="MyWPFDemo1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyWPFDemo1"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>
/// <summary>
/// App.xaml 的交互逻辑
/// </summary>
public partial class App : Application
{
}
1.3. MainWindow.xaml 和 MainWindow.xaml.cs
一样的,一个UI元素代码,一个是后台交互逻辑代码
<Window x:Class="MyWPFDemo1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MyWPFDemo1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
</Grid>
</Window>
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
2. 正式开始分析
2.1. 声明即定义
首先我们要知道xaml语法中声明即定义,意思就是"见到元素就相当于创建实例",MainWindow.xaml的主干是一个Window
元素里包含着一个 Grid
元素。
这段程序就是在定义一个Window类的实例,这个实例的一个组成部分是一个Grid类的实例。
<Window>
<Grid>
</Grid>
</Window>
2.2. 命名空间
<Window x:Class="MyWPFDemo1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MyWPFDemo1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
</Grid>
</Window>
上面看着很像主页地址的东西,它们都是些什么呢 ? 让我们来一个一个地分析 。
2.2.1. xaml的Property和Attribute
XAML是一种由XML派生而来的语言,所以很多XML中的概念在XAML是通用的。比如,使用标签声明一个元素 (每个元素对应内存中的一个对象) 时,需要使用起始标签和终止标签, 夹在起始标签和终止标签中的XAML代码表示是隶属于这个标签的内容。如果没有什么内容隶属于某个标签,则这个标签称为空标签,可以写为 。
为了表示同类标签中的某个标签与众不同,可以给它的特征 (Attribute) 赋值。 为特征赋值的语法如下:
● 非空标签:<Tag Atributel=Valuel Attribute2=Value2>Content</Tag>
● 空标签:<Tag Atributel=Valuel Attribute2=Value2></Tag>
在这里,有必要把Attribute和Property这两个词仔细地辨别一下。
这两个词的混淆由来已久。混淆的主要原因就是大多数中文译本里既把Atribute译为"属性 ",也把Property译为"属性"。
其实,这两个词所表达的不是一个层面上的东西。
Property属于面向对象理论范畴。在使用面向对象思想编程的时候,常常需要对客观事物进行抽象,再把抽象出来的结果封装成类,类中用来表示事物状态的成员就是Property。比如要写一个模拟赛车的游戏,那么必不可少的就是对现实汽车的抽象。现实中的汽车身上会带有很多数据但在游戏中可能只关心它的长度、宽度、高度、重量、速度等有限的几个数据,例如,Car.Length,Car.Height,Car.Speed,这些都是Property的典型代表,将Property译为"属性"也很贴切。总结一句话就是:Property是针对对象而言的。
Attribute则是编程预约文法层面的东西。比如有两个同类的语法元素A和B,为了表示A与B不完全相同或者A与B在用法上有些区别,这时候就压针对A和B加一些Attribute。总结一句话:Attribute只与语言层面上的东西有关,与抽象出来的对象没有什么关系。因为Attribute是为了表示"区分"的,所以把它译为"特征"。
显然Attribute只是用来影响类在程序中的用法,而Property则对应着抽象对象身上的性状,他们根本不是一个层面上的东西。
2.2.2. xaml中命名空间
下面代码都是Window
标签的Attribute:
x:Class="MyWPFDemo1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MyWPFDemo1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800"
其中Title,Height, Width一看就知道与Window对象的Property相对应。
中间xmlns(xml namespace的简写)是在声明名称空间,语法格式如下:
xmlns[:可选的映射前缀]="名称空间",xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
这个没有加映射前缀的名称空间称为"默认名称空间",说明很多的wpf控件都是来自这个命名空间。
如果改为xmlns:w,那下面的Grid前面也需要加上w前缀。
<Window x:Class="MyWPFDemo1.MainWindow"
xmlns:w="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
...
Title="MainWindow" Height="450" Width="800">
<w:Grid>
</w:Grid>
</Window>
总结一点就是上面这些xmlns同C#引用程序集的操作都是一个目的,都是为了引入自己需要的外部程序集。但是xaml里面引入的好像是个网页地址?其实把它copy到IE的地址栏里尝试跳转也不会打开网页。
这里只是XAML解析器的一个硬性编码(hard-coding),只要见到这些固定的字符串,就会把一系列必要的程序集(Assembly)和程序集中包含的NET名称空间引用进来。
哦,原来微软也有硬编码~
也不用太担心手写这些命名空间,IDE也是能有智能提示的。。
2.2.3. partial关键字
一个类能够"掰成两半"来写,这要归功于partial这个关键字,使用这个关键字,可以把一个类的代码分散在多处来实现。
可问题又来了------XAML代码怎么和C#代码"对接"啊?不用担心微软的xaml解析器在背后把这件事完成了。因为XAML代码中没有逻辑,所以,解析XAML的大部分工作就是按照元素标签的描述把对象创建出来------比如,解析器见到有Grid
标签出现,就会生成与C#代码new Grid()等价的代码。
最后,使用partial关键字,可以把一个类分拆在多处定义,只要各部分代码不冲突即可。显然,由XAML解析器生成的MainWindow类在声明时也使用了partial关键字,这样,由XAML解析成的类和C#文件里定义的部分就合二为一。正是由于这种partial机制,我们可以把类的逻辑代码留在.cs文件里,用C#语言来实现,而把那些与声明及布局UI元素相关的代码分离出去,实现UI与逻辑分离。
并且,用于绘制UI的代码(如声明控件类型的字段、设置它们的外观和布局等)也不必再使用C#语言使用XAML和XAML编辑工具就能轻松搞定!
至此,你应该对这个最简单的XAML程序了然于胸了。