教程1:XAML快速指南
教程1:XAML快速指南
本教程描述了XAML语言的功能,并演示了如何使用XAML编写noesisGUI接口。即使有生成XAML的工具,您也需要了解或调整XAML。有时候,当您想要精细控制或想知道发生了什么时,手工编写UI会更容易。
什么是XAML?
XAML是一种声明性标记语言,可用于创建应用程序UI,例如控件,形状,文本和其他显示在屏幕上的内容。如果您熟悉Web编程,则可以认为XAML与HTML相似。像HTML一样,XAML由元素和属性组成。XAML基于XML的,因此必须遵循XML规则。
XAML直接表示对象的实例化。以下示例显示了如何创建按钮作为UI的一部分:
<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Button Content="Click Me!"/>
</Grid>
注意
稍后在本文档中说明根元素中的xmlns属性。
对于UI,XAML比过程代码更易于阅读且更紧凑。但是在极少数情况下,有必要使用过程代码动态创建UI。以下代码等效于上面显示的XAML:
C ++
Ptr<Button> button = *new Button();
button->SetContent("Click Me!");
Ptr<Grid> grid = *new Grid();
grid->GetChildren()->Add(button);
C#
Button button = new Button();
button.Content = "Click Me!";
Grid grid = new Grid();
grid.Children.Add(button);
使用像XAML这样的声明性语言的一个好处是,在组成UI的标记和应用程序执行操作的代码之间具有一定的分离。例如,您团队中的设计人员可以设计一个UI,然后将XAML交给开发人员以添加过程代码。即使设计人员和开发人员是同一个人(通常如此),您也可以将视觉内容保存在XAML文件(.xaml)中,而将过程UI代码保存在代码隐藏文件(.cs和.cpp)中。
XAML语法简介
以下各节说明XAML语法的基本形式。如果您以前熟悉XML语言,那么接下来的几节中的大部分材料您会感觉很熟悉。这是XAML的基本设计原则之一。XAML语言定义了自己的概念,但是这些概念在XML语言和标记形式中同样起作用。
XAML对象元素(Object Elements)
一个对象元素(object element)通常声明一个类型的实例。对象元素语法始终以尖括号(<)开头。之后是要在其中创建实例的类型的名称。该名称可能包含前缀,稍后将对其进行解释。之后,您可以选择在object元素上声明属性。为使对象元素标签完整,请以右尖括号(>)结尾。也可以使用不具有任何内容的自闭合的形式——通过正斜杠和相继闭合尖括号(*/> *)结束标签。例如,再次查看先前显示的标记片段:
<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Button Content="Click Me!"/>
</Grid>
它指定了两个对象元素:<Grid>(带有内容和一个结束标记),和<Button ... />(具有多个属性的自动闭合形式)。对象元素Grid和Button分别映射到由noesisGUI定义的类名称。指定对象元素标记时,将创建XAML处理指令来创建新实例。在解析和加载XAML时,通过调用基础类型的默认构造函数来创建每个实例。
属性(Properties)
对象的属性通常可以表示为对象元素的属性。属性语法为要设置的属性命名,之后为赋值运算符(=)。属性值始终指定为引号中包含的字符串。
属性语法是最简化的属性设置语法,也是过去使用过标记语言的开发人员所使用的最直观的语法。在下一个示例中,我们创建一个红色矩形Rectangle。我们将Fill属性设置为预定义的颜色名称,XAML解析器会将其转换为适合Fill属性的SolidColorBrush。
<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Rectangle Fill="Red" />
</Grid>
属性元素(Property Element)
对于对象元素的某些属性,属性语法不可用,因为提供属性值所需的对象或信息无法在属性语法的引号和字符串限制内充分表达。对于这些情况,可以使用属性元素语法(property element syntax)。
属性元素语法的开始标记为<typeName.propertyName>。通常,该标签的内容是作为该属性value类型的对象元素。指定内容后,必须使用结束标记结束属性(property)元素。结束标记的语法为</typeName.propertyName>。
如果可以使用属性语法,使用属性语法通常会更方便并且可以实现更紧凑的标记,这通常只是样式问题,而不是技术限制。以下示例显示了与前面的属性语法示例中设置的属性相同的属性,但是这次通过对Button的所有属性使用属性元素语法来进行设置。
<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Rectangle>
<Rectangle.Fill>
<SolidColorBrush Color="Red"/>
</Rectangle.Fill>
</Rectangle>
</Grid>
下一个示例创建一个Rectangle,但是它使用由LinearGradientBrush创建的渐变来代替简单的红色填充。
<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<!-- This rectangle is painted with a diagonal linear gradient. -->
<Rectangle Width="200" Height="200">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1.0" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
集合(Collection)语法
XAML语言包括一些可产生更多可读标记的优化。例如,如果特定属性采用集合类型,则您在标记中声明为该属性值内的子元素的项目将成为集合的一部分。在这种情况下,子对象元素的集合是设置为collection属性的值。
以下示例显示了一个Grid容器,其中包含一个元素Rectangle。
<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Rectangle />
</Grid>
XAML内容属性(Content Properties)
XAML指定一种语言功能,通过该功能,类可以将其属性指定为XAML内容属性。该对象元素的子元素用于设置该内容(content)属性的值。换句话说,对于content属性来说,您可以在XAML标记中设置那个属性元素时省略它,并在标记中产生一个更明显的父/子隐喻。
例如,Border指定Content属性为Child。以下两个Border元素被相同地对待。第一个利用内容属性语法,并省略Border.Child属性元素。第二个显式显示Border.Child。
<Border>
<TextBox Width="300"/>
</Border>
<!--explicit equivalent-->
<Border>
<Border.Child>
<TextBox Width="300"/>
</Border.Child>
</Border>
如果声明为XAML内容属性的属性是Object类型或String类型,则XAML内容语法支持XML文档模型中的基本内部文本:在开始和结束对象标签之间的字符串。例如,TextBlock中的Text属性用于设置Text,但是字符串“ Text”从不出现在标记中。这是一个示例用法:
<TextBlock>Hello!</TextBlock>
事件(Events)属性
属性语法也可以用于事件而不是属性的成员。在这种情况下,属性的名称是事件的名称。您在此处提供的是事件处理函数的函数名称。该功能必须在XAML页面的代码背后(code-behind)定义。例如,以下标记将Click事件的处理程序分配给在标记中创建的Button:
<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>
标记扩展(Markup Extensions)
标记扩展(Markup extensions)是XAML语言的概念。当用于提供属性语法的值时,大括号({和})用于标记扩展名。这种用法使XAML处理摆脱了对属性值作为文字字符串或字符串可转换值的一般处理。
noesisGUI中最常用的标记扩展是Binding(用于数据绑定表达式),资源引用StaticResource和DynamicResource。通过使用标记扩展,即使该属性通常不支持属性语法,也可以使用属性语法为属性提供值。标记扩展通常使用中间表达式类型来启用诸如推迟值(deferring values)或引用仅在运行时出现的其他对象类的功能。
例如,以下标记使用属性语法设置Style属性的值。该样式属性采用的实例样式类,它在默认情况下无法通过属性语法的字符串来实例化。但是在这种情况下,该属性引用了特定的标记扩展,即StaticResource。处理该标记扩展时,它将返回对样式的引用,该样式先前已实例化为资源字典中的键控资源。
<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid.Resources>
<SolidColorBrush x:Key="MyBrush" Color="Gold"/>
<Style TargetType="Border" x:Key="PageBackground">
<Setter Property="Background" Value="{StaticResource MyBrush}"/>
</Style>
</Grid.Resources>
<Border Style="{StaticResource PageBackground}" />
</Grid>
类型转换器(Type Converters)
在“ 属性语法”部分中,已声明必须能够通过字符串设置属性值。如何将字符串转换为其他对象类型或原始值的基本本地处理基于String类型本身。但是,许多noesisGUI类型或这些类型的成员扩展了基本的字符串属性处理行为,从而可以将更复杂的对象类型的实例指定为字符串和属性。
厚度(Thickness)结构是具有类型转换为XAML用途启用的类型的一个例子。厚度(Thickness)表示嵌套矩形内的尺寸,并用作诸如Margin之类的属性的值。通过将一个类型转换器厚度,使用一个所有属性厚度更容易在XAML来指定,因为它们可以被指定为属性。下面的示例使用类型转换和属性语法为Margin提供值:
<Button Margin="10,20,10,30" Content="Click me"/>
前面的属性语法示例等效于下面的更详细的语法示例,在此示例中,“ 边距Margin”是通过包含“ 厚度Thinkness”对象元素的属性元素语法设置的。厚度的四个关键属性被设置为新实例的属性:
<Button Content="Click me">
<Button.Margin>
<Thickness Left="10" Top="20" Right="10" Bottom="30"/>
</Button.Margin>
</Button>
XAML根目录和命名空间
一个XAML文件必须只有一个根元素,才能成为格式正确的XML文件和有效的XAML文件。对于典型方案,您使用在应用程序模型中具有突出含义的根元素(例如,页面的Window或Page,外部词典的ResourceDictionary或应用程序定义的Application)。以下示例显示了典型XAML文件的root元素和Page的root元素。
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</Page>
根元素还包含属性xmlns和xmlns:x。这些属性向XAML处理器指示哪些XAML命名空间包含标记将引用为元素的支持类型的类型定义。该XMLNS属性明确表示默认XAML命名空间。在默认的XAML命名空间内,可以在标记中指定对象元素而没有前缀。出于兼容性目的,默认XAML命名空间映射到WPF命名空间http://schemas.microsoft.com/winfx/2006/xaml/presentation
。所述的xmlns:X属性指示的附加XAML命名空间,它映射XAML语言命名空间http://schemas.microsoft.com/winfx/2006/xaml
。
请注意,xmlns属性仅在每个XAML文件的根元素上严格必需,xmlns定义将应用于该根元素的所有子元素。
x:前缀(x:Prefix)
以下是您将使用的最常见的x:前缀编程构造的清单:
- x:Key:为ResourceDictionary中的每个资源设置唯一的键,x:Key可能占典型标记中x:用法的90%。
- x:Name:将此属性添加到任何您希望能够作为代码隐藏逻辑的一部分引用创建的运行时实例的XAML对象元素上。
- x:Class:指定为XAML页面提供代码隐藏的类的名称空间和类名称。您必须具有此类来支持后台代码,因此即使没有资源,您几乎总是看到x:映射。
- x:Type:基于类型名称构造Type引用。这用于指定采用Type的属性,例如Style :: TargetType,尽管通常该属性具有本机字符串到Type的转换,使得x:Type标记扩展名的使用是可选的。
- x:Null:如果需要在XAML中指定null值。
附加属性和事件
XAML指定一种语言功能,该功能允许在任何元素上指定某些属性或事件,而不管所设置元素的类型定义中是否存在该属性或事件。此功能的属性版本称为附加属性,事件版本称为附加事件。从概念上讲,您可以将附加属性和附加事件视为可以在任何XAML元素实例上设置的全局成员。
XAML中的附加属性通常通过属性语法使用。在属性语法中,您可以使用ownerType.propertyName形式指定一个附加属性。附加属性的最常见方案是使子元素能够向其父元素报告属性值:
<Canvas>
<Button Canvas.Left="50">Hello</Button>
</Canvas>