XAML基础知识

XAML(Extensible Application Markup Language)可扩展应用程序标记语言。XAML与WPF是两个概念,但XAML主要用来构造 WPF 用户界面。

学习WPF之前必须先了解XAML,XAML中的属性又是XAML的基础。

一、简单属性(属性-特性语法)

<TextBox Name="txtQuestion" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" FontFamily="Verdana" FontSize="24" Foreground="Green" ... >

为使这个系统能够工作, XAML 解析器需要执行比表面上看起来更多的工作。 XML 特性中的值总是纯文本字符串。但对象的属性可以是任何.NET 类型。

在上面的示例中,有两个属性为枚举类型(VerticalAlignment 属性和 HorizontalAlignment 属性)、 一个为字符串类型(FontFamily属性)、一个为整型(FontSize 属性),还有一个为 Brush 对象(Foreground 属性)。

为了关联字符串值和非字符串属性, XAML 解析器需要执行转换。 由类型转换器执行转换,类型转换器是从.NET 1.0 起就已经引入的.NET 基础结构的一个基本组成部分。

与所有基于 XML 的语言一样, XAML 也区分大小写。这意味着不能用 <button>替代<Button> 。 然而 , 类型转换器通常不区分大小写 ,这意味着Foreground="White" 和Foreground="white"具有相同的效果。

二、复杂属性(属性-元素语法)

虽然类型转换器便于使用,但它们不能解决所有的实际问题。例如,有些属性是完备的对象,这些对象具有自己的一组属性。尽管创建供类型转换器使用的字符串表示形式是可能的,但使用这种方法时语法可能十分复杂,并且容易出错。

幸运的是, XAML 提供了另一种选择:属性元素语法(property-element syntax)。使用属性元素语法, 可添加名称形式为 Parent.PropertyName 的子元素。

例如, Grid 控件有一个 Background 属性,该属性允许提供用于绘制控件背景区域的画刷。 如果希望使用更复杂的画刷——比单一固定颜色填充更高级的画刷——就需要添加名为 Grid.Background 的子标签。

<Grid Name="grid1">
<Grid.Background>
<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.00" Color="Red" />
<GradientStop Offset="0.50" Color="Indigo" />
<GradientStop Offset="1.00" Color="Violet" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Grid.Background>
...
</Grid>

三、标记扩展

对大多数属性而言, XAML 属性语法可以工作得非常好。但有些情况下,不可能硬编码属性值。例如,可能希望将属性值设置为一个已经存在的对象,或者可能希望通过将一个属性绑定到另一个控件来动态地设置属性值。

这两种情况都需要使用标记扩展——一种以非常规的方式设置属性的专门语法。标记扩展可用于嵌套标签或 XML 特性中(用于 XML 特性的情况更常见)。 当用在特性中时,它们总是被花括号{}包围起来。

例如,下面的标记演示了如何使用标记扩展,它允许引用另一个类中的静态属性:<Button ... Foreground="{x:Static SystemColors.ActiveCaptionBrush}" >标记扩展使用{标记扩展类 参数}语法。

在上面的示例中, 标记扩展是 StaticExtension 类(根据约定,在引用扩展类时可以省略最后一个单词 Extension)。 x 前缀指示在 XAML 名称空间中查找 StaticExtension 类。还有一些标记扩展是 WPF 名称空间的一部分,它们不需要 x 前缀。

四、附加属性

除普通属性外, XAML 还包括附加属性(attached property)的概念——附加属性是可用于多个控件但在另一个类中定义的属性。在 WPF 中,附加属性常用于控件布局。

<TextBox ... Grid.Row="0">
...
</TextBox>

附加属性根本不是真正的属性。它们实际上被转换为方法调用。 与其他所有 WPF 控件一样, TextBox 控件继承自DependencyObject 基类。

DependencyObject 类旨在存储实际上没有限制的依赖项属性的集合(前面讨论的附加属性是特殊类型的依赖项属性)。

附加属性是 WPF 的核心要素,优于将该属性作为基类的一部分呢。

五、嵌套元素

XAML 文档被排列成一棵巨大的嵌套的元素树。Window元素包含 Grid 元素, Grid 元素又包含 TextBox 元素和 Button 元素。

XAML 让每个元素决定如何处理嵌套的元素。这种交互使用下面三种机制中的一种进行中转,而且求值的顺序也是下面列出这三种机制的顺序:

● 如果父元素实现了 IList 接口,解析器将调用 IList.Add( )方法,并且为该方法传入子元素作为参数。

● 如果父元素实现了 IDictionary 接口,解析器将调用 IDictionary.Add( )方法,并且为该方法传递子元素作为参数。当使用字典集合时,还必须设置 x:Key 特性以便为每个条目指定键名。

● 如果父元素使用 ContentProperty 特性进行修饰,解析器将使用子元素设置对应的属性。

六、特殊字符与空白

七、事件

到目前为止介绍的所有特性都被映射为属性。然而,特性也可用于关联事件处理程序。用于关联事件处理程序的语法为:事件名 ="事件处理程序方法名 "。

例如, Button 控件提供了 Click 事件。可使用如下所示的标记关联事件处理程序:<Button ... Click="cmdAnswer_Click">

上面的标记假定在代码隐藏类中有名为 cmdAnswer_Click 的方法。事件处理程序必须具有正确的签名 (也就是说,必须匹配 Click 事件的委托)。

许多情况下,将使用特性为同一元素设置属性和关联事件处理程序。 WPF 总是遵循以下顺序:首先设置 Name 属性(如果设置的话),然后关联任意事件处理程序,最后设置其他属性。

这意味着,所有对属性变化做出响应的事件处理程序在第一次设置属性时都会被触发。

本文参考《WPF编程宝典C#2012》

原文地址:https://www.cnblogs.com/hryan/p/8032441.html