WPF之旅(二)- XAML
什么是XAML
XAML(Extensible Application Markup Lanaguage的简写,发音“zammel”)是用于实例化.NET对象的标记语言。尽管XAML是一种可以用于诸多不同问题领域的技术,但其主要作用是构造WPF用户界面。换言之,XAML文档定义了在WPF应用程序中组成窗口的面板、按钮以及各种控件的布局。
WPF之前的图形用户设计界面存在的问题
1. 每个图形元素(背景和按钮等)需要导出为单独的位图。这限制了组合位图的能力和使用动态效果的能力,如反锯齿、透明和阴影效果。
2. 相当多的用户界面逻辑都需要开发人员嵌入到代码中,图形设计人员无法控制其中的任何细节。
3. 在不同的图形元素之间没有固有的连接,经常会使用不匹配的图像集合。
4. 在调整图形大小时必然会损失质量。基于位图的界面依赖于分辨率,这意味着它不能适应大显示器以及高分辨率显示设置。
XAML变体
我们使用XAML表示整个XAML语言,它是一种基于通用XML语法,专门用于表示一颗.NET对象树的语言,它包括如下几个集合:
1. WPF XAML包含描述WPF的内容元素。
2. XPS XAML是WPF XAML的一部分,它为格式化的电子文档定义了一种XML表示方式。
3. Silverlight XML是一个用于Microsoft Silverlight应用程序的WPF XAML子集。
4. WF XAML包含描述WF(Work FLOW,工作流)内容的元素。
XAML编译
WPF使用BAML(Binary Application Markup Lanaguage,二进制应用程序标记语言)来克服这个缺点。BAML并非新事物,它实际上就是XAML的二进制表示,所有XAML都被转换成BAML,然后这些BAML作为资源被嵌入到最终的DLL或EXE程序集中。大多数程序员不用考虑XAML向BAML的转换,因为编译器会在后台执行这项工作。但也可以使用未经编译的XAML,这对于需要即时提供一些用户界面的情况可能有意义的(例如从某个数据库中提取内容作为一块XAML标签)。
XAML标准
1. XAML文档中的每个元素都映射为.NET类的一个实例,元素的名称也完全对应于类名。
2. 与所有XML文档一样,可在一个元素嵌套另一个元素。
3. 可通过特性(Attribute)设置每个类的属性(Property),在某种情况下,特性不足以完成既需要通过特殊的语法使用嵌套的标签(tag)。
XAML的命名空间
xmlns特性是XML中的一个特殊特性,它专门用来声明名称空间,在创建的所有WPF XAML中都会出现这两个命名空间。
1. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"是WPF核心命名空间。它包含了所有WPF类,包括用来构建用户界面的控件。
2. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"是XAML命名空间。它包括了各种XAML实用特性,这些特性可影响文档的解释方式。该命名空间被映射为前缀x。这意味着可通过在元素名称之前放置命名空间前缀x来使用该命名空间(例如:<x:ElementName>),
“x”前缀/XAML语言XAML命名空间常见的结构:
x:key:为XAML ResourceDictionary中的每一个资源设置唯一的用户定义密匙。
x:class:为XAML页面提供代码隐藏类指定代码命名空间和代码名称。例如<window x:Class="WindowApplication1.Window1">。
x:Name:在处理XAML中定义的对象元素后,为运行时代码中存在的对象指定一个运行时的对象名。你可将在XAML中设置x:Name看作是代码中声明命名变量。例如:<Grid x:Name="grid1">
x:Uid:标识某些元素,应将本地化后的资源用与该元素的一些属性值。如下图资源文件:

将控件关联到资源文件:<TextBlock x:Uid="Greeting" Text="" />
XAML中的属性和事件
1. 类型转换器:为了关联字符串值和非字符串属性,XAML解析器需要执行转换。由类型转换器执行转换,其提供了使用的方法,可将特定的.NET数据类型转换为任何其他.NET类型或将任何其他.NET类型转换为指定的数据类型。XAML通过两个步骤来查找类型转换器:
a. 检查属性声明,查找TypeConverter特性。
b. 如果属性声明中没有TypeConverter,XAML解析器将检查对应数据类型的类声明。
注意:与所有基于XML的语言一样,XAML也区分大小写,这意味着不能用<button>替代<Button>, 然而,类型转换器通常不区分大小写,这意味着ForeGround="White"和ForeGround="white"具有相同的效果。
2. 复杂属性
虽然类型转换器便于使用,但他们不能解决所有的实际问题,幸运的是XAML提供另一种选择:属性元素语法(property-element-syntax)。使用属性元素语法,可添加名称形式为Parent.PropertyName的子元素。例如:
<Grid>
<Grid.Background>
Blue
</Grid.Background>
</Grid>
真正起作用的是元素名中的句点(.)。这个句点把该属性和其他类型的嵌套内容区分开来。这个句点把该属性和其他类型的嵌套内容区分开来。下面我们来看下嵌套属性:
<Grid>
<Grid.Background>
<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.00" Color="Red"></GradientStop>
<GradientStop Offset="0.50" Color="Indigo"></GradientStop>
<GradientStop Offset="1.00" Color="Violet"></GradientStop>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Grid.Background>
</Grid>
任何XAML标签集合都可以用一系列执行相同任务的代码语句替换,上面显示的标签与以下代码等价:
var brush = new LinearGradientBrush();
var gradientStop1 = new GradientStop();
gradientStop1.Offset = 0;
gradientStop1.Color = Colors.Red;
brush.GradientStops.Add(gradientStop1);
var gradientStop2 = new GradientStop();
gradientStop2.Offset = 0.5;
gradientStop2.Color = Colors.Indigo;
brush.GradientStops.Add(gradientStop2);
var gradientStop3 = new GradientStop();
gradientStop3.Offset = 1;
gradientStop3.Color = Colors.Violet;
brush.GradientStops.Add(gradientStop3);
grid1.Background = brush;
3. 标记扩展
标记扩展允许XAML文件访问只根据支持类型声明元素的值或行为,对大多数属性而言,XAML属性语法可以工作得非常好。但有些情况,不能硬编码属性值,例如,可能希望将属性值设置为一个已经存在的对象,或者可能希望通过一个属性绑定到另一个控件来动态得设置属性值,这些情况下都需要使用标记扩展-一种以非常规的方式设置属性的专门语法。
标记扩展可用于嵌套标签或XML特性中,当用于特性中时,他们总是被花括号{}包围起来。例如:
<Button Foreground="{x:Static SystemColors.ActiveCaptionBrush}"></Button>
标记扩展使用{标记扩展类 参数}语法。在上面示例中,标记扩展是StaticExtension类(根据约定,在引用扩展类时可以省略最后一个单词Extension)。x前缀指示在XAML名称空间中查找StaticExtension类。上面的XAML的最终结果和下面代码相同:
cmdBtn.Foreground = SystemColors.ActiveCaptionBrush;
因为标记扩展映射为类,所以他们也可以用作嵌套属性,如下:
<Button>
<Button.Foreground>
<x:Static Member="SystemColors.ActiveCaptionBrush"></x:Static>
</Button.Foreground>
</Button>
4. 附加属性
附加属性(attached property)是XAML中引入的编程概念,借此,特殊类型可以拥有和定义属性,但在任何元素上都将属性设置为特性或者属性元素。它的工作原理是每个控件有个子固有的属性(例如,文本框有其特定的字体,文本颜色吗,这些通过FontFamily, ForeGround属性指定的)。当在容器放置控件时,根据容器的类型控件会获得额外特征。
附加属性使用使用包含两个部分的命名形式:定义类型.属性名。例如,通过附加属性在网格的每一行放置各个控件:
<TextBox Grid.Row="0">Some words</TextBox>
<TextBox Grid.Row="1">Some words</TextBox>
附加属性根本不是真正的属性,他们实际上被转换为方法调用。XAML解析器采用以下形式的调用静态方法:DefiningType.SetPropertyName()。例如,在上面的XAML代码中,定义类型为Grid类,并且属性是Row,所以解析器调用Grid.SetRow()方法,具体为: Grid.SetRow(txtAns,0)。
5. 嵌套元素
XAML文档被排列成一棵巨大的嵌套的元素树,XAML让每个元素决定如何处理嵌套的元素,这种交互使用下面三种机制中的一种,而且求值的顺序也是下面列出的这三种机制的顺序:
a. 如果父元素实现了IList接口,解析器将调用IList.Add()方法,并且该方法传入子元素作为参数。
b. 如果父元素实现了IDictionary接口,解析器将调用IDictionary.Add()方法,并且为该方法传递子元素作为参数。当时用字典集合时,还必须设置x:Key特性以便为每个条目指定键名。
c. 如果父元素使用ContentProperty特性进行修饰,解析器将使用子元素设置对应的属性。
6. 特殊字符与空白
XAML受到XML规则的限制,如果我们试图使用一些特殊字符,例如,&,<和>,将会遇到麻烦,因为XAML解析器认为你正在处理其他事情。有时候这并不是期望的结果,这些情况下,需要为元素使用特定的转换,例如<l替代<, >替代>,当希望文本包含一系列空格,需要为元素使用xml:space="preserve"特性。
XAML的事件
特性也可以用于关联事件处理程序,语法为:事件名="事件处理程序方法名",例如:
<Button ... Click="cmdBtn_Click"></Button>
下面是一个和要求的方法:
private void cmdBtn_Click(object sender, RoutedEventArgs e)
{
//do something else
}
当添加事件处理程序特性时,VS的只能感应可提供极大的帮助,VS会显示一个包含代码隐藏类中的所有合适的事件处理程序的下拉列表,用户可以选择并创建这个事件处理程序。
本人最近开始学习WPF以及DevExpress,藉此提升自己C/S架构编程的能力。在学习过程会有一些心得体会,于是便会写一些博客来记录这些想法,有兴趣的朋友可以和我一起交流学习。那么就让我们从这里开始WPF与DevExpress的旅程吧!
QQ群: 32745894,欢迎大家加入讨论!
WPF之旅(二)- XAML的更多相关文章
- WPF数据绑定Binding(二)
WPF数据绑定Binding(二) 1.UI控件直接的数据绑定 UI对象间的绑定,也是最基本的形式,通常是将源对象Source的某个属性值绑定 (拷贝) 到目标对象Destination的某个属性上. ...
- WPF,Silverlight与XAML读书笔记第三十九 - 可视化效果之3D图形
原文:WPF,Silverlight与XAML读书笔记第三十九 - 可视化效果之3D图形 说明:本系列基本上是<WPF揭秘>的读书笔记.在结构安排与文章内容上参照<WPF揭秘> ...
- WPF疑难杂症之二(全屏幕窗口)
原文:WPF疑难杂症之二(全屏幕窗口) 近日的学习中遇到一个非常奇怪的问题:用XAML文件创建了一个全屏幕窗口,然后,在窗口中建立了一个非常简单的动画.一切都在我的掌控之中,实现非常的顺利. WPF中 ...
- WPF案例(二)模拟Apple OS 界面前后180度反转
原文:WPF案例(二)模拟Apple OS 界面前后180度反转 我们在设计应用程序界面的时候,为了充分利用界面空间,住住需要灵活的界面布局方式,比如可以在界面正面空间上定义一个Chart,背面空间上 ...
- WPF自定义控件(二)の重写原生控件样式模板
话外篇: 要写一个圆形控件,用Clip,重写模板,去除样式引用圆形图片可以有这三种方式. 开发过程中,我们有时候用WPF原生的控件就能实现自己的需求,但是样式.风格并不能满足我们的需求,那么我们该怎么 ...
- WPF 访问外部的xaml文件
原文:WPF 访问外部的xaml文件 今天做主题时,需要访问外部的xaml文件,方法: using (FileStream s = new FileStream("C:\\Control.x ...
- WPF系列教程——(二)使用Prism实现MVVM设计模式 - 简书
原文:WPF系列教程--(二)使用Prism实现MVVM设计模式 - 简书 本文假设你已经知道MVVM设计模式是什么,所以直接进入正题,今天我们就用Prism来实现WPF的MVVM设计模式,百度上关于 ...
- WPF,Silverlight与XAML读书笔记(3) - 标记扩展
hystar的.Net世界 博客园 首页 新闻 新随笔 联系 管理 订阅 随笔- 103 文章- 0 评论- 107 WPF,Silverlight与XAML读书笔记(3) - 标记扩展 说 ...
- wpf convert png to xaml
原文:wpf convert png to xaml 把png图片转化成xaml资源 <ResourceDictionary xmlns="http://schemas.microso ...
- WPF中的Generic.xaml, theme以及custom control
原文:WPF中的Generic.xaml, theme以及custom control 在Visual Studio中创建自定义控件时,所有控件都将添加到/Themes/Generic.xaml. 最 ...
随机推荐
- Android 在程序中动态添加 View 布局或控件
有时我们需要在程序中动态添加布局或控件等,下面用程序来展示一下相应的方法: 1.addView 添加View到布局容器 2.removeView 在布局容器中删掉已有的View 3.LayoutPar ...
- redis(二)Redis适用场景,如何正确的使用
网络IO模型 Memcached是多线程,非阻塞IO复用的网络模型,分为监听主线程和worker子线程,监听线程监听网络连接,接受请求后,将连接描述字pipe 传递给worker线程,进行读写IO, ...
- windows 10 笔记本关机不断电解决
右键我的电脑-->管理-->设备管理器-->系统设备 找到Intel(R) Management Engine Interface 双击打开,禁用,确定,完事 原因,该驱动11.0 ...
- 操作系统是怎么工作的——函数的堆栈框架/嵌入式代码
1.函数堆栈框架 1.1框架模型 call指令: 1)将eip中的下一条指令的地址A保存在栈顶: 2)设置eip指向被调用程序的代码处. ret指令:将地址A恢复到eip中 这样就将函数的调用变为顺序 ...
- centos 6.5 samba简单配置
1.安装samba yum -y install samba (我的显示已经安装啦!) 2.编辑samba的配置文件 vi /etc/samba/smb.conf 用 testparm查看我配置后的 ...
- [HttpException (0x80004005): The current identity
[HttpException (0x80004005): The current identity (IIS APPPOOL\NationalUnion.Shared) does not have w ...
- Retrofit入门
1 Retrofit retrofit = new Retrofit.Builder() .addConverterFactory(ScalarsConverterFactory.create()) ...
- C#多线程案例基础
C#多线程案例基础(转) 在学习多线程之前,我们先来看几个概念: 1,什么是进程? 当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源,当然一个程序也可能开 ...
- nodejs安装及环境配置
简单的说 Node.js 就是运行在服务端的 JavaScript. Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台. Node.js是一个事件驱动I/O服务端Ja ...
- hadoop-集群管理(2)——内存设置
http://www.cnblogs.com/yuechaotian/archive/2013/03/08/2949607.html 1. 内存 hadoop为各个守护进程(namenode,seco ...