XAML 概述二
通过上一节我们已经对XAML有了一定的了解,这一节我们来系统的学习一下XAML。
一. 简单属性与类型转换器,属性元素:
我们已经知道 XAML是一种声明性的语言,并且XAML解析器会为每个标签创建一个与之对应的对象。光有对象是没有任何意义的,需要对属性之类的赋值才有使用意义。所以就要求XAML为对象属性赋值。XAML中为对象属性赋值共有2种语法:
· 使用字符串进行简单赋值
· 使用属性元素进行复杂赋值
<TextBox VerticalAlignment="Stretch" HorizontalAlignment="Stretch" FontFamily="Verdana" FontSize="14" Foreground="Gray">XAML</TextBox>
为了使上面的设置起作用,System.Windows.Controls.TextBox类必须提供上面面这些属性。
上面的设置中,有2个属性为枚举类型(VerticalAlignment,HorizontalAlignment),一个FontFamily类型,一个double类型(FontSize)和一个SolidColorBrush类型(Foreground)。在XAML中,Attribute的值总是一个字符串的值。为了使之能正常工作,XAML解析器悄悄的执行了类型转换:
1.首先检查属性声明,查找该属性是否使用了TypeConverter特性;如果使用了就能进行类型转换。
2.如果属性声明中没有使用TypeConverter特性,就查找数据类型的类的声明;如果使用了就能进行类型转换。
如果属性和类中都没有声明,XAML解析器就会生成一个错误。
[Category("Appearance"), Localizability(LocalizationCategory.None), TypeConverter(typeof(FontSizeConverter)), Bindable(true)]
public double FontSize
{
get
{
return (double)base.GetValue(FontSizeProperty);
}
set
{
base.SetValue(FontSizeProperty, value);
}
} [Category("Appearance"), Bindable(true)]
public Brush Foreground
{
get
{
return (Brush)base.GetValue(ForegroundProperty);
}
set
{
base.SetValue(ForegroundProperty, value);
}
}
我们查看源代码就可以看到,FontSize属性声明了TypeConverter特性,但是Brush没有。我们再查看Brush类声明的源代码,就会发现有一个TypeConverter(typeof(BrushConverter))特性。其中BrushConverter,FontSizeConverter都是实现了TypeConverter的类型转换类。
虽然类型转换器很方便,但是不能解决所有的问题。有些属性是完备的对象,这些对象有着自己的一系列属性。如果继续使用类型转换器的话,语法会很复杂,也有可能出错。幸好XAML提供了一种更好的选择:属性元素。其语法为:
<ClassName>
<ClassName.AttributeName></ClassName.AttributeName>
</ClassName>
重要的就是中间的那个点(.)
二.标记扩展(Markup Extensions)
仔细观察XAML中为对象属性赋值的语法,大多数都是为属性生成一个新对象。但有的时候需要把同一个对象赋值给两个对象的属性,还有时候需要给对象的属性赋null值,或者赋值为一个静态对象等。这个时候就需要标记扩展了。
有2种方式可以设置标记扩展:
· 当用于提供特性值时,语法就是左右大括号({ 和 })。 然后,由紧跟在左大括号后面的字符串标记来标识标记扩展的类型。
· 当用在属性元素语法中时,标记扩展在外观上与其他任何用于提供属性元素值的元素相同,即:一个将标记扩展类作为一个元素引用并以尖括号 (<>) 括起的 XAML 元素声明。
尽管标记扩展的语法简单方便,但是不是所有的对象都能使用标记扩展的语法来书写。只有直接或间接实现了System.Windows.Markup.MarkupExtension 的类才能使用标记扩展。
标记扩展并不多,它们是:
· XAML定义的标记扩展:x:Type 、x:Static、x:Null、x:Array (这几个后面介绍x命名空间的时候会介绍到它们的用法,它们并非是 XAML 的 WPF 实现所特有的,而是语言形式的 XAML 的内部函数或功能实现。)
· 特定于WPF的标记扩展:StaticResource、DynamicResource、Binding、RelativeSource、TemplateBinding、ColorConvertedBitmap、ComponentResourceKey、ThemeDictionary (后面的章节中会介绍它们中部分的用法)
最后要注意一下几点:
· 标记扩展是可以嵌套的,逗号表示各个标记的分隔符,例如:
<TextBox Text="{Binding Source={StaticResource Person},Path = Name}"></TextBox>
· 标记扩展有一些简写语法,如{Binding Name,...}与{Binding Path = Name,...}是等价的。两种写法中,前者称为固定位置参数(Positional Parameter),后者称为具名参数(Named Parameters)。固定位置参数实际就是构造函数的参数,其位置由构造函数参数列表决定。如果是具名参数,则会首先为标记扩展调用默认构造函数;之后,每个“名称=值”对都会被解释为标记扩展上存在的属性名称以及赋给该属性的值。
· 标记扩展类几乎以单词Extension为后缀(Binding除外),在XAML中使用的时候可以全写StaticResourceExtension,也可以简写StaticResource。其实这点只用知道就行,我们在用Visaul Studio的时候,智能感知就已经帮我们用简写的方式了。
三.附加属性
附加属性是由 XAML 定义的概念。附加属性是可以用于多个控件但在一个类中定义的属性。通常的语法为:AttachedPropertyProvider.PropertyName。
<Grid>
<TextBox Grid.Row="0">XAML</TextBox>
</Grid>
后面有章节会专门讲到附加属性,到时候再专门讲它。
四.嵌套元素
正如我们看到,XAML文档被排列成一个巨大的嵌套元素的树。XAML中有3种机制可以决定如何处理嵌套元素:
· 如果父元素实现了IList接口,解析器就会调用IList.Add()方法,并且为该方法传入子元素作为参数。
· 如果父元素实现了IDictionary接口,解析器就会调用IDictionary.Add()方法,并为该方法传入子元素作为参数。当使用字典集合的时候,必须使用x:Key特性以便为每个条目指定键名。
<TextBox>
<TextBox.Background>
<LinearGradientBrush>
<GradientStopCollection>
<GradientStop Offset="0" Color="Red"></GradientStop>
<GradientStop Offset="0.5" Color="LavenderBlush"></GradientStop>
<GradientStop Offset="1" Color="WhiteSmoke"></GradientStop>
</GradientStopCollection>
</LinearGradientBrush>
</TextBox.Background>
</TextBox>
我们查看GradientStopCollection类的源码,就可以发现它实现了IList接口,所以解析器把每个GradientStop以IList.Add()的方式添加到集合中。
· 如果父元素使用了ContentProperty特性,解析器就会使用子元素设置其对应的属性。
列如我们的查看Grid的源代码,虽然该类没有使用ContentProperty特性,但是Grid的父类Panel类使用了该特性ContentProperty("Children")。这表明应该使用任何嵌套元素来设置Children属性。XAML解析器会根据是否是一个集合属性(集合属性是否实现了IList接口和IDictionary接口),以不同的方式来处理内容属性。因为Panel.Children返回的是一个UIElementCollection对象,并且该对象实现了IList接口,所以解析器使用IList.Add()方法把嵌套的元素添加到集合中。
var grid = new Grid();
var textBox = new TextBox();
grid.Children.Add(textBox);
嵌套的内容不完全就是一个集合,我们查看TextBox,发现它ContentProperty("Text")指向的是一个Text属性,并且该属性返回的是一个string类型。所以TextBox的嵌套元素只能为一个字符串。
还一个Button类,我们知道它的直接基类ButtonBase,并没有发现ContentProperty特性;然后再往上找ContentControl这个基类,就发现了ContentProperty("Content")指向的是Content属性;查找该属性,就会发现它返回的是一个object类型。所有可以在Button中嵌套任何元素。
五.事件
到目前为止,介绍的所有Attribute都被映射为Property。然后,Attribute也可以关联事件处理程序。如果使用Visual Studio的话,就可以自动的帮我们完成事件和后台代码的创建与关联。
也可以使用Code元素,直接在XAML文档中嵌入代码(如事件处理程序)。
<StackPanel>
<Button Content="Button" Click="button_Click"></Button>
</StackPanel> <x:Code>
<![CDATA[
private void button_Click(object sender,RoutedEventArgs e)
{
MessageBox.Show("Bye!Code-Behind!");
}
]]>
</x:Code>
不过最好不要使用这一做法,WPF中并不需要使用这一技术,不值得推荐。
六.导入程序集和引用其中的命名空间
这个使用很简单,只需要把需要引用的dll添加到程序引用。然后再使用xmlns:Prefix="clr-namespace:NameSpace;assembly=AssemblyName"语法就行。
Prefix:命名空间前缀。
NameSpace:完全限定的.NET命名空间名称
AssemblyName:声明类型的程序集,没有.dll扩展名
七.注释与特殊符号
XAML的注释语法继承自XML。语法为:<!--需要注释的内容-->
不过有几点需要注意:
· 注释只能出现在标签的内容区域,也就是说只能出现在开始和结束标签之间
· 注释不能用于标签的Attribute
· 注释不能嵌套
特殊的符号:
特殊字符 | 字符实体 |
< | < |
> | > |
& | & |
" | " |
接下来的一节,我们会了认识一下x命名空间下的具体内容。
XAML 概述二的更多相关文章
- XAML 概述
我们将向 Windows 运行时应用开发人员介绍 XAML 语言和 XAML 概念,并介绍在使用 XAML 创建 Windows 运行时应用时,在 XAML 中声明对象和设置属性的不同方式. 什么是 ...
- {MySQL数据库初识}一 数据库概述 二 MySQL介绍 三 MySQL的下载安装、简单应用及目录介绍 四 root用户密码设置及忘记密码的解决方案 五 修改字符集编码 六 初识sql语句
MySQL数据库初识 MySQL数据库 本节目录 一 数据库概述 二 MySQL介绍 三 MySQL的下载安装.简单应用及目录介绍 四 root用户密码设置及忘记密码的解决方案 五 修改字符集编码 六 ...
- XAML 概述四
这一节我们来简单介绍一下XAML的加载和编译,它包括如下三种方式: · 只使用代码 · 使用代码和未编译的XAML · 使用代码和编译过的BAML 一. 只使用代码 我们首先创建一个简单的控制台 ...
- XAML 概述三
通过对前面2节对XAML的介绍,我们对XAML有了一定的认识.这一节我们来简单了解一下部分XAML命名空间(x:)语言功能. x命名空间映射的是http://schemas.microsoft.com ...
- 一、 JSP概述 二、JSP的语法结构 三、JSP内置对象
一.JSP概述###<1>概念 java服务器页面 可以编写动态页面 其内部是以HTML标签为主,可以在HTML标签嵌套java代码 jsp文件以.jsp为后缀 jsp本质上就是一个Ser ...
- 一、JavaScript概述 二、JavaScript的语法 三、JavaScript的内置对象
一.JavaScript的概述###<1>JavaScript的概念 又称ECMAScript,和java没有任何关系 嵌入在HTML元素中的 被浏览器解释运行的 一种脚本语言. ###& ...
- 一、HTML概述 二、web相关的概念 三、HTML的常用标签
一.HTML概述###<1>概念 HTML:Hypertext Markup Language,超文本 标记语言,用来描述网页的一种语言. 非编程语言,由浏览器直接解释运行. ###< ...
- 一、CSS概述 二、CSS的选择器(认识) 三、CSS样式和属性(练习) 四、重构商城首页DIV+CSS(页面布局)(重点) 浮动/更改显示方式
一.CSS概述###<1>概念 DIV,就是一个HTML元素,块级元素,通常结合CSS进行页面的布局. CSS,层叠样式表,给HTML元素增强显示. ###<2>作用 样式定义 ...
- 一、Linux概述 二、Linux的安装 三、Linux的常用命令(重点)
一.Linux概述###<1>操作系统 OS,管理和控制 计算机的 硬件和软件资源的 计算机程序. 最基本的系统软件. 是用户和计算机交互的桥梁,是硬件和软件交互的桥梁. 操作系统:she ...
随机推荐
- C#中Dictionary小记
使用C#中Dictionary的一下细节小记: 一.Dictionary.Add(key,value) 与 Dictionary[key]=value的区别: 如果Dictionary中已经有了key ...
- VMware系统运维(十四)部署虚拟化桌面 Horzion View Manager 5.2 配置许可
1.通过网页访问https://conntionserver.testad.local/admin,打开如下图所示页面:输入用户名密码 2.进来以后配置View 许可,点击"编辑许可证&qu ...
- Matlab之文件操作
1.判断是否存在文件夹:if (exist(folderName,'dir')) 2.创建文件夹:mkdir(folderName) 3.删除文件夹:rmdir(folderName,'s') 4.当 ...
- 在IIS上发布项目后浏览时报的错:Unable to make the session state request to the session state server
错误描述: Unable to make the session state request to the session state server. Please ensure that the A ...
- c#中的方法的定义和运用
首先,理解下,函数和方法: 其实两者是一样的,只是个叫法不同. C#中叫做Method,中文叫方法: C++中称为Function,中文叫函数. 函数是Function,多指以前面向过程编程时候,将逻 ...
- php学习笔记6--php中的文件包含 include,require,include_once,require_once
php中的文件包含 include,require,include_once,require_once 文件包含:是指将一个文件的内容包含进另外一个文件,有利于代码的复用等.php中文件包含指令有4个 ...
- 说一说Android的工程目录结构
这段时间正在学习有关Android的知识,对在Eclipse下开发的Android项目的目录结构有了一定的了解,在此对目录结构做一个简单的介绍.下图是在Eclipse下Android项目展开的项目目录 ...
- js标签放在html的什么位置比较好
推荐的是js的script标签放在body的末尾,</body>标签之前,包含在body内! <body> <!--其它Html标签--> <script&g ...
- leetcode题1Two sum 练习
题目为: 给一个整数数组, 返回数组中的两数之和等于指定值的两数在数组中的下标. Example: Given nums = [2, 7, 11, 15], target = 9, Because n ...
- 第三方框架、AFN、ASI、SDWebImage
AFN 一.2大管理对象1.AFHTTPRequestOperationManager* 对NSURLConnection的封装 2.AFHTTPSessionManager* 对NSURLSessi ...