XAML概述
一:语法概述
1:XAML 对象元素
1 <StackPanel> 2 <Button Content="Click Me"/> 3 </StackPanel>
此示例指定了两个对象元素:<StackPanel>(含有内容,后面有一个结束标记)和 <Button .../>(自结束形式,包含几个特性)
指定对象元素标记时会创建一条 XAML 处理指令来创建一个新实例。 每个实例都是在分析和加载 XAML 时通过调用基础类型的默认构造函数来创建的。
2:CLR的属性表示
①特性语法
<Button Background="Blue" Foreground="Red" Content="This is a button"/>
②属性元素语法
1 <Button> 2 <Button.Background> 3 <SolidColorBrush Color="Blue"/> 4 </Button.Background> 5 <Button.Foreground> 6 <SolidColorBrush Color="Red"/> 7 </Button.Foreground> 8 <Button.Content> 9 This is a button 10 </Button.Content> 11 </Button>
3:集合语法
<LinearGradientBrush> <LinearGradientBrush.GradientStops> <!-- no explicit new GradientStopCollection, parser knows how to find or create --> <GradientStop Offset="0.0" Color="Red" /> <GradientStop Offset="1.0" Color="Blue" /> </LinearGradientBrush.GradientStops> </LinearGradientBrush>
4:XAML 内容属性
XAML 指定了一个语言功能,通过该功能,一个类可以指定它的一个且仅一个属性为 XAML 内容属性。 该对象元素的子元素用于设置该内容属性的值。 换言之,仅对内容属性而言,您可以在 XAML 标记中设置该属性时省略属性元素,并在标记中生成更直观的父级/子级形式。
<Border> <TextBox Width="300"/> </Border> <!--explicit equivalent--> <Border> <Border.Child> <TextBox Width="300"/> </Border.Child> </Border>
5:文本内容
有少量 XAML 元素可直接将文本作为其内容来处理。 若要实现此功能,必须满足以下条件之一:
-
类必须声明一个内容属性,并且该内容属性必须是可赋值给字符串的类型(该类型可以是 Object)。 例如,任何 ContentControl 都将 Content 用作其内容属性,并且其类型为 Object,这样就支持实际的 ContentControl(例如,Button)上的如下用法:<Button>Hello</Button>。
-
类型必须声明一个类型转换器,该类型转换器将文本内容用作其初始化文本。 例如,<Brush>Blue</Brush>。 这种情况实际上并不常见。
-
类型必须为已知的 XAML 语言基元。
6:内容属性和集合语法组合
<StackPanel> <Button>First Button</Button> <Button>Second Button</Button> </StackPanel>
此例中,每个 Button 都是 StackPanel 的一个子元素。 这是一个简单直观的标记,其中出于两个不同的原因省略了两个标记。
-
省略的 StackPanel.Children 属性元素: StackPanel 从 Panel 派生。 Panel 将 Panel.Children 定义为其 XAML 内容属性。
-
省略的 UIElementCollection 对象元素: Panel.Children 属性采用类型 UIElementCollection,该类型实现 IList。 根据处理集合(例如 IList)的 XAML 规则,集合的元素标记可以省略。 (在这种情况下,UIElementCollection 实际无法实例化,因为它没有公开默认构造函数,这就是 UIElementCollection 对象元素以注释形式出现的原因。)
1 <StackPanel> 2 <StackPanel.Children> 3 <!--<UIElementCollection>--> 4 <Button>First Button</Button> 5 <Button>Second Button</Button> 6 <!--</UIElementCollection>--> 7 </StackPanel.Children> 8 </StackPanel>
7:事件
特性语法
<Page 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> </Page>
对象元素、属性元素和特性名称均必须使用区分大小写的形式指定
值并不总是区分大小写。 值是否区分大小写将取决于与采用该值的属性关联的类型转换器行为,或取决于属性值类型。 例如,采用 Boolean 类型的属性可以采用 true 或 True 作为等效值,但只是因为将字符串转换为 Boolean 的本机 WPF XAML 分析器类型转换已经允许将这些值作为等效值。
XAML 将空格、换行符和制表符转化为空格,如果它们出现在一个连续字符串的任一端,则保留一个空格。
三:标记扩展
标记扩展是一个 XAML 语言概念。 当用于提供特性语法的值时,大括号({ 和 })表示标记扩展用法。 此用法指示 XAML 处理系统不要像通常那样将特性值视为一个文本字符串或者可转换为字符串的值。
1 <Page.Resources> 2 <SolidColorBrush x:Key="MyBrush" Color="Gold"/> 3 <Style TargetType="Border" x:Key="PageBackground"> 4 <Setter Property="Background" Value="Blue"/> 5 </Style> 6 7 8 ... 9 10 11 </Page.Resources> 12 <StackPanel> 13 <Border Style="{StaticResource PageBackground}"> 14 15 16 ... 17 18 19 </Border> 20 </StackPanel>
四:类型转换器
<Button Margin="10,20,10,30" Content="Click me"/>
上面的特性语法示例与下面更为详细的语法示例等效,但在下面的示例中,Margin 改为通过包含 Thickness 对象元素的属性元素语法进行设置。 而且设置 Thickness 的四个关键属性作为新实例的特性:
<Button Content="Click me"> <Button.Margin> <Thickness Left="10" Top="20" Right="10" Bottom="30"/> </Button.Margin> </Button>
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" ... </Page>
x: 前缀
-
x:Key:为 ResourceDictionary(或其他框架中的类似字典概念)中的每个资源设置唯一的键。 在典型的 WPF 应用程序标记中的所有 x: 用法中,x:Key 将可能占到 90%。
-
x:Class:向为 XAML 页提供代码隐藏的类指定 CLR 命名空间和类名。 必须具有这样一个类才能支持每个 WPF 编程模型的代码隐藏,而正是因此,即使没有资源,也几乎总是能看到映射的 x:。
-
x:Name:处理对象元素后,为运行时代码中存在的实例指定运行时对象名称。 通常,您将为 x:Name 经常使用 WPF 定义的等效属性。 此类属性特定映射到 CLR 后备属性,因此更便于进行应用程序编程,在应用程序编程中,您经常使用运行时代码从初始化的 XAML 中查找命名元素。 最常见的此类属性是 FrameworkElement.Name。 在特定类型中不支持等效的 WPF 框架级 Name 属性时,仍然可以使用 x:Name。 某些动画方案中会发生这种情况。
-
x:Static:启用一个返回静态值的引用,该静态值只能是一个 XAML 兼容属性。
-
x:Type:根据类型名称构造一个 Type 引用。 它用于指定采用 Type(例如 Style.TargetType)的特性,但属性经常具有本机的字符串到 Type 的转换功能,因此使用 x:Type 标记扩展用法是可选的。
下面是一个说明自定义前缀如何在 XAML 标记中工作的基本示例。 前缀 custom 在根元素标记中定义,并映射为随应用程序一同打包并可用于该应用程序的一个特定程序集。 此程序集包含 NumericUpDown 类型,实现该类型的目的是在支持常规 XAML 用法之外,还可以使用允许在 WPF XAML 内容模型的此特定点执行插入的类继承。 通过使用该前缀,此 NumericUpDown 控件的一个实例声明为对象元素,以便 XAML 分析器可找到包含该类型的 XAML 命名空间,从而找到包含该类型定义的后备程序集的位置。
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:custom="clr-namespace:NumericUpDownCustomControl;assembly=CustomLibrary" > <StackPanel Name="LayoutRoot"> <custom:NumericUpDown Name="numericCtrl1" Width="100" Height="60"/> ... </StackPanel> </Page>
<Page 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> </Page>
1 namespace ExampleNamespace 2 { 3 public partial class ExamplePage 4 { 5 void Button_Click(object sender, RoutedEventArgs e) 6 { 7 Button b = e.Source as Button; 8 b.Foreground = Brushes.Red; 9 } 10 } 11 }
<StackPanel Name="buttonContainer"> ... <Button Click="RemoveThis">Click to remove this button</Button> </StackPanel>
void RemoveThis(object sender, RoutedEventArgs e) { FrameworkElement fe = e.Source as FrameworkElement; if (buttonContainer.Children.Contains(fe)) { buttonContainer.Children.Remove(fe); } }
<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>