WPF从入门到放弃系列第二章 XAML
本文是作者学习WPF从入门到放弃过程中的一些总结,主要内容都是对学习过程中拜读的文章的整理归纳。
参考资料
- XAML 概述 (WPF):https://msdn.microsoft.com/zh-cn/library/ms752059.aspx
- XAML 语法详述:https://msdn.microsoft.com/zh-cn/library/ms788723.aspx
- 闲话WPF之二(XAML概述):http://www.cnblogs.com/YilingLai/archive/2006/12/14/591944.html
- [MS-XAML]XAML语言规范(哪位大神翻译一下啊)::http://go.microsoft.com/fwlink/?LinkId=114525
- WPF XAML 的 XAML 命名空间和命名空间映射:https://msdn.microsoft.com/zh-cn/library/ms747086.aspx
- XAML 中的空白处理:https://msdn.microsoft.com/zh-cn/library/ms788746.aspx
- 标记扩展和 WPF XAML:https://msdn.microsoft.com/zh-cn/library/ms747254.aspx
- TypeConverters 和 XAML https://msdn.microsoft.com/zh-cn/library/aa970913.aspx
- xamalot http://www.xamalot.com/
什么是XAML
XAML 是一种声明性标记语言。 XAML 简化了为 .NET Framework 应用程序创建 UI 的过程。 可以在声明性 XAML 标记中创建可见的 UI 元素,然后使用代码文件(通过分部类定义与标记相连接)将 UI 定义与运行时逻辑相分离。 XAML 直接以程序集中定义的一组特定后备类型表示对象的实例化。这与大多数其他标记语言不同,后者通常是与后备类型系统没有此类直接关系的解释语言。 XAML 实现了一个工作流,通过此工作流,各方可以采用不同的工具来处理应用程序的 UI 和逻辑。
以文本表示时,XAML 文件是通常具有 .xaml 扩展名的 XML 文件。 可通过任何 XML 编码对文件进行编码,但通常编码为 UTF-8。
下面的内容表示一个带有一个按钮的WINDOW窗体的XAML描述
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ExampleNamespace.ExamplePage">
<Button Click="Button_Click" >Click Me!</Button>
</Window>
XAML语法介绍
XAML 中的大小写和空白
XAML 区分大小写。 按名称与程序集中的基础类型进行比较或者与类型的成员进行比较时,对象元素、属性元素和特性名称均必须使用区分大小写的形式指定。 XAML 语言关键字和基元也区分大小写。 值并不总是区分大小写。 值是否区分大小写将取决于与采用该值的属性关联的类型转换器行为,或取决于属性值类型。 例如,采用 Boolean 类型的属性可以采用 true 或 True 作为等效值。
WPF XAML 处理器和序列化程序将忽略或删除所有无意义的空白,并规范化任何有意义的空白。 这与 XAML 规范的默认空白行为建议一致。 通常,只有当您在 XAML 内容属性中指定字符串时,此行为的重要性才会体现出来。 简言之,XAML 将空格、换行符和制表符转化为空格,如果它们出现在一个连续字符串的任一端,则保留一个空格。
对象元素
对象元素将XAML中的元素与.NET中的类映射,对象元素以左尖括号(<)始,右面紧跟着类名。对象元素可以包含零个或多个特性,使用空格分隔每一个"特性="值""对。元素定义必须满足下面两条
元素和标记需要已
/>
结尾开始标记必须以
>
结尾。其他对象元素、属性元素或者内部文本可以跟在开始标记后面。可以包含的内容会受到到模型约束。<StackPanel>
<Button Content="Click Me"/>
</StackPanel>
上面的代码声明了两个对象元素StackPanel
和Button
,运行时两个对象元素会映射成System.Windows.Controls.StackPanel
和System.Windows.Controls.Button
类的对象,映射出的Button对象的Content属性会被设置为"Click Me",创建对象时会调用默认的构造函数(无参构造函数)。
特性元素
特性是用来描述对象元素的属性,特性名必须是对象元素相关类的属性或者事件,并且该属性或事件的访问级别应该是public
的。
特性值的处理
目前没有掌握,只了解了有三种特性的特性值是被特殊处理的。
- 带有{}大括号的特性值
- 如果属性是用特性化 TypeConverter 声明的(目前还不明白)
- 如果没有 TypeConverter(目前还不明白)
枚举特性值
设置枚举特性值时,不能使用枚举的具体值,而要通过指定枚举的某个命名常量的字符串名称。
设置枚举特性值时,不需要使用枚举类型.枚举值
的方式,可以直接使用枚举值的字符串。
如果枚举是按位枚举,可以使用,
分隔多个枚举值。
属性元素
在XML中特性的值一般是字符串,但是字符串并不能很好的描述对象之间的关联。在XAML中可以指定对象元素为 属性的值,但是并不将属性指定为元素标记内的特性,而是使用元素的开始标记指定“元素类型名称.属性名称”形式的属性,在其中指定属性的值,然后结束属性元素。
例如,下面的属性元素语法针对的是Button
的ContextMenu
属性
<Button>
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="1">First item</MenuItem>
<MenuItem Header="2">Second item</MenuItem>
</ContextMenu>
</Button.ContextMenu>
Right-click me!</Button>
集合语法
在XAML中可以添加值为集合类型的属性元素。但属性元素必须继承自
- IList
- IDictionary
- Array
集合检测功能不支持泛型列表和字典接口(IList 和 IDictionary<TKey, TValue>)。 但是,可以将 List 类用作基类(因为它直接实现 IList),或者将 Dictionary<TKey, TValue> 用作基类(因为它直接实现 IDictionary)。
如果属性的值是集合类型的不需要以对象元素的形式指定集合的类型,集合中的项标记为属性元素的一个或者多个子元素。我们将这种集合称为隐式集合
下面的例子是显示集合的对象元素的语法,并不是所有的集合都可以显示声明,显示声明要求集合必须支持默认构造函数。
<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Offset="0.0" Color="Red" />
<GradientStop Offset="1.0" Color="Blue" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
除了根元素,XAML文件中另一个元素的子元素形式嵌套的每个对象元素实际上属于下面两种情况之一:父元素的隐式集合属性成员,父元素指定XAML内容属性的元素。。换言之,一个标记页上的父元素与子元素之间的关系实际上就是一个根对象,而根对象下面的每个对象元素要么是为父元素提供属性值的一个实例,要么是同样作为父元素的集合类型属性值的集合中的一项。
内容属性
一个类可以指定它的一个且仅一个属性为 XAML 内容属性,指定的方法是在类声明时加ContentPropertyAttribute
特性,并设置内容属性的NAME
。可以在 XAML 标记中设置该属性时省略属性元素。
例如:Border
指定内容属性Child
。系统处理下面两个Border元素的方式相同。 第一个元素利用了内容属性语法而省略了Border.Child
属性元素。 第二个元素显式标明Border.Child
。
<Border>
<TextBox Width="300"/>
</Border>
<!--显示指定-->
<Border>
<Border.Child>
<TextBox Width="300"/>
</Border.Child>
</Border>
XAML 内容属性的值必须完全在该对象元素的其他任何属性元素之前或之后指定。 无论将 XAML 内容属性的值指定为字符串还是指定为一个或多个对象都是如此。
文本内容
有少量XAML元素可以直接将文本作为期内容。但必须满足以下条件之一:
- 类必须声明一个内容属性,并且该内容属性必须是可符值给字符串的类型(可以是
Object
)例如,任何ContentControl
都将Content
用作其内容属性,并且其类型为Object
,这样就支持实际的ContentControl
,Button
上的如下用法:<Button>Hello</Button>
。 - 类型必须声明一个类型转换器,该类型转换器将将文本内容作为初始化文本。例如,
<Brush>Blue</Brush>
。 - 类型是已知的 XAML 语言基元类型
内容属性与特殊元素不能混合使用下面的代码会报错
<Button Content="This example">This example</Button>
内容属性和集合语法组合
当内容属性的类型为集合时,则不需要标记中指定隐含的集合类型为对象元素,也不需要指定该XAML内容属性作为属性元素。
所有 Panel 派生类都证实 XAML 内容属性为 Children(它要求值为 UIElementCollection 类型)
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<StackPanel>
<Button>Button 1</Button>
<Button>Button 2</Button>
<Button>Button 3</Button>
</StackPanel>
</Page>
标记中既不需要 Children 的属性元素也不需要 UIElementCollection 的元素。
标记扩展
标记扩展是一种动态占位符,当用于特性元素值时,大括号{}
表示扩展语法。XAML遇到这样的符号以后,就不在把属性值作为字符串处理了。 左大括号后面的第一个字符串必须引用用来提供特定扩展行为的类,如果子字符串“Extension”是实际类名的一部分,则该引用可以省略这个子字符串
.NET XAML 实现使用 MarkupExtension 抽象类作为 WPF 以及所有其他框架或技术支持的所有标记扩展的基础。 WPF 特定实现的标记扩展通常用于提供一种方法来引用其他已经存在的对象,或者对将在运行时计算的对象进行延迟引用。 例如,通过指定用Binding
标记扩展代替特定属性通常将采用的值,从而实现简单的 WPF 数据绑定。 对于无法以其他方式使用特性语法的属性,许多 WPF 标记扩展都允许使用特性语法。 例如,Style 对象是一种相对复杂的类型,其中包含一系列嵌套的对象和属性。 WPF 中的样式通常定义为 ResourceDictionary 中的资源,之后将通过请求资源的两个 WPF 标记扩展之一来引用。 标记扩展将属性值的计算推迟到查找资源时进行,并允许在特性语法中提供 Style 属性的值并采用 Style 类型,如下例所示:
Button Style="{StaticResource MyStyle}">My button</Button>
在这里,StaticResource 用来标识 StaticResourceExtension 类,该类提供标记扩展实现。 下一个字符串 MyStyle 用作非默认 StaticResourceExtension 构造函数的输入,在该构造函数中,从扩展字符串提取的参数将声明所请求的 ResourceKey。 MyStyle 应当是定义为资源的 Style 的 x:Key 值。 StaticResource 标记扩展 用法要求使用该资源,在加载时通过静态资源查找逻辑来提供 Style 属性值。
类型转换器
特性元素值必须设定为字符串,但是对字符串如何转换为其他对象类型或基元值的基本类型处理取决于 String
类型本身,以及对某些类型(如 DateTime 或 Uri)的本机处理。 但是很多 WPF 类型或这些类型的成员扩展了基本字符串特性处理行为,因此可以指定更复杂的对象类型的实例作为字符串和特性。
下面的示例使用类型转换和特性语法来为 Margin 提供值,Margin的类型为Thickness
,该类型可以实现类型转换。
<Button Margin="10,20,10,30" Content="Click me"/>
[an error occurred while processing the directive]
附加属性和附加事件
在特性中使用附加属性的语法为所有者类型.属性名
的形式
所有者类型”始终是一种与从中要设置附加属性的对象元素不同的类型。 “所有者类型”这种类型提供 XAML 处理器为获取或设置附加属性值所需要的访问器方法。
使用附加属性的最常见方案是使子元素能够向其父元素报告属性值。
下面的示例演示了 DockPanel.Dock 附加属性。 DockPanel 类为 DockPanel.Dock 定义访问器,因此拥有附加属性。 DockPanel 类还包括一个逻辑,该逻辑迭代其子元素并具体检查每个元素是否具有 DockPanel.Dock 设置值。 如果找到一个值,将在布局过程中使用该值定位子元素。
<DockPanel>
<Button DockPanel.Dock="Left" Width="100" Height="20">I am on the left</Button>
<Button DockPanel.Dock="Right" Width="100" Height="20">I am on the right</Button>
</DockPanel>
看了一些文章还不能很好的理解。
[an error occurred while processing the directive]
根元素和命名空间
下表显示了一个经过分解的典型 XAML 根元素,同时显示了根元素的具体特性:
<Page | 根元素的开始对象元素 |
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | 默认 (WPF) XAML 命名空间 |
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | XAML 语言 XAML 命名空间 |
x:Class="ExampleNamespace.ExampleCode" | 类声明,它将标记连接到为类定义 |
> | 根的对象元素的末尾。 由于该元素包含子元素,因此对象未结束 |
请注意,只有在每个 XAML 文件的根元素上,xmlns 特性才是绝对必需的。 xmlns 定义将适用于根元素的所有子代元素。同时允许根以下的其他元素上具有 xmlns 特性,这些特性将适用于定义元素的任何子代元素。 但是,频繁定义或重新定义 XAML 命名空间可能会导致 XAML 标记样式难以阅读。
WPF从入门到放弃系列第二章 XAML的更多相关文章
- WPF从入门到放弃系列第一章 初识WPF
什么是WPF WPF(Windows Presentation Foundation)是微软推出的基于Windows Vista的用户界面框架,属于.NET Framework 3.0的一部分.它提供 ...
- 我与PHP,ULM和Vue.js不得不说的故事(一个放荡不羁与一个神神秘秘一个似曾相识,从入门到放弃记录第二章)
·关于UML(git) 究竟是命运在茫茫语言之中遇到了你,还是我的魅力让你向我奔涌而来.好吧都不是,我俩就像古代包办婚姻,被专业牢牢的绑在一起了,既然都是一条绳上的蚂蚱.我我们应该能体谅彼此的不容易, ...
- K8S 从入门到放弃系列文章目录(Kubernetes 1.14)
1)软件环境 软件 版本 系统 Centos7.5 Kubernetes 1.14.1 Docker 18.09 Calico 3.6 Etcd 3.3.12 2)部署过程简单概要 三台master节 ...
- [大数据从入门到放弃系列教程]在IDEA的Java项目里,配置并加入Scala,写出并运行scala的hello world
[大数据从入门到放弃系列教程]在IDEA的Java项目里,配置并加入Scala,写出并运行scala的hello world 原文链接:http://www.cnblogs.com/blog5277/ ...
- [大数据从入门到放弃系列教程]第一个spark分析程序
[大数据从入门到放弃系列教程]第一个spark分析程序 原文链接:http://www.cnblogs.com/blog5277/p/8580007.html 原文作者:博客园--曲高终和寡 **** ...
- php从入门到放弃系列-01.php环境的搭建
php从入门到放弃系列-01.php环境的搭建 一.为什么要学习php 1.php语言适用于中小型网站的快速开发: 2.并且有非常成熟的开源框架,例如yii,thinkphp等: 3.几乎全部的CMS ...
- php从入门到放弃系列-04.php页面间值传递和保持
php从入门到放弃系列-04.php页面间值传递和保持 一.目录结构 二.两次页面间传递值 在两次页面之间传递少量数据,可以使用get提交,也可以使用post提交,二者的区别恕不赘述. 1.get提交 ...
- php从入门到放弃系列-03.php函数和面向对象
php从入门到放弃系列-03.php函数和面向对象 一.函数 php真正的威力源自它的函数,内置了1000个函数,可以参考PHP 参考手册. 自定义函数: function functionName( ...
- php从入门到放弃系列-02.php基础语法
php从入门到放弃系列-02.php基础语法 一.学习语法,从hello world开始 PHP(全称:PHP:Hypertext Preprocessor,即"PHP:超文本预处理器&qu ...
随机推荐
- C#_MVC 自定义AuthorizeAttribute实现权限管理
随笔- 28 文章- 31 评论- 16 MVC 自定义AuthorizeAttribute实现权限管理 在上一节中提到可以使用AuthorizeAttribute进行权限管理: [Autho ...
- [置顶] Objective-C开发环境介绍以及Cocoa,以及第一个程序
Objective-C 起源与发展 Brad J. Cox designed the Objective-C language in the early 1980 . 布兰德于1980年设计的 ...
- eclipse引用头文件报错问题-解决方法
最近在做一个U-BOOT相关的项目,经过几天的折腾最终放弃使用VIM和一堆附加插件.最终的出的结论是对于中大型工程项目还是要启用一些专业的IDE比较稳妥,尽管VIM提供的各种插件累加在一起足以实现专业 ...
- 2013 ACM/ICPC 长沙现场赛 C题 - Collision (ZOJ 3728)
Collision Time Limit: 2 Seconds Memory Limit: 65536 KB Special Judge There's a round medal ...
- 用Cookie记住上次登录用户名
一个登录页面设置查看Cookie中的数据(Cookie不为null);然后将页面提交到另一个页面去,在这个页面中的到是否选择记住用户名,如果选择了, 就创建Cookie对象,将用户名存储起来,下次登录 ...
- client 如何找到正确的RegionServer(HBase -ROOT-和.META.表)
在HBase中,大部分的操作都是在RegionServer完成的,Client端想要插入,删除,查询数据都需要先找到相应的RegionServer.什么叫相应的RegionServer?就是管理你要操 ...
- SQLSERVER2012用户登录error40
昨天晚上公司停电了,电脑非正常关闭,今早回来之后,用sa登录sqlserver,一直报error40这个错,以前没碰到过,所以很紧张,问东问西,在网上也搜了好多,也跟着配置了好多,都不行,快被逼疯的时 ...
- (转) VS2012程序打包部署详解
程序编写测试完成后接下来我们要做的是打包部署程序,但VS2012让人心痛的是没有了打包工具.不知道出于什么原因微软没有将打包工具集成在开发环境中,但是我知道总会有解决办法的. 经过翻阅资料发现 ...
- 给div设置一个关闭按钮.
造轮子好难. 用惯了框架提供的组件,某天自己要做个伪组件(或者在他人创建的页面效果上添加新功能)会发现很难. 所以,碰到了,就一定要做下记录.以供日后查阅. 如图,弹出DIV右上角的关闭按钮是我此次添 ...
- 10_Jaxws使用自定义pojo发布服务
[简述] 查询三天的天气信息(天气概况.日期.温度),测试jaxws是否支持自定义pojo发布服务. [开发过程] 服务端: 1.自定义pojo(天气概况.日期.温度) 2.开发SEI接口及实现类 3 ...