基本 XAML 语法
XAML 主要用于实例化和初始化对象。 但通常,属性必须设置为无法轻易用 XML 字符串表示的复杂对象,有时必须对子类设置由一个类定义的属性。 满足这两个要求需使用属性元素和附加属性的基本 XAML 语法功能。
属性元素
在 .NET Multi-platform App UI (.NET MAUI) XAML 中,类的属性通常设置为 XML 属性:
<Label Text="Hello, XAML!"
VerticalOptions="Center"
FontAttributes="Bold"
FontSize="18"
TextColor="Aqua" />
但是,还可通过另一种方法在 XAML 中设置属性:
<Label Text="Hello, XAML!"
VerticalOptions="Center"
FontAttributes="Bold"
FontSize="18">
<Label.TextColor>
Aqua
</Label.TextColor>
</Label>
这两个指定 TextColor
属性的示例在功能上是等效的,并介绍了一些基本术语:
- Label 是一个对象元素。 它是一个以 XML 元素表示的 .NET MAUI 对象。
Text
、VerticalOptions
、FontAttributes
和FontSize
是属性特性。 它们是以 XML 特性表示的 .NET MAUI 属性。- 在第二个示例中,
TextColor
已成为属性元素。 它是一个以 XML 元素表示的 .NET MAUI 属性。
注意
在属性元素中,属性的值始终定义为属性元素开始标记和结束标记之间的内容。
还可以对一个对象的多个属性使用属性元素语法:
<Label Text="Hello, XAML!"
VerticalOptions="Center">
<Label.FontAttributes>
Bold
</Label.FontAttributes>
<Label.FontSize>
Large
</Label.FontSize>
<Label.TextColor>
Aqua
</Label.TextColor>
</Label>
虽然属性元素语法看似不必要,但当属性的值过于复杂而无法用简单字符串表示时,该语法至关重要。 在属性元素标记中,可以实例化另一个对象并设置其属性。 例如,Grid 布局具有名为 RowDefinitions
和 ColumnDefinitions
的属性,它们的类型分别为 RowDefinitionCollection
和 ColumnDefinitionCollection
。 这些类型是 RowDefinition
和 ColumnDefinition
对象的集合,通常使用属性元素语法进行设置:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.GridDemoPage"
Title="Grid Demo Page">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
...
</Grid>
</ContentPage>
附加属性
在前面的示例中,可以看到 Grid 需要 RowDefinitions
和 ColumnDefinitions
集合的属性元素来定义行和列。 这表明必须有一种方法来指示 Grid 的每个子级所在的行和列。
在 Grid 的每个子级的标记中,使用 Grid.Row
和 Grid.Column
特性(默认值为 0)指定该子级的行和列。 还可以使用 Grid.RowSpan
和 Grid.ColumnSpan
特性(默认值为 1)指示子级是否跨多行或多列。
以下示例演示如何将子级放在 Grid 内:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.GridDemoPage"
Title="Grid Demo Page">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<Label Text="Autosized cell"
TextColor="White"
BackgroundColor="Blue" />
<BoxView Color="Silver"
Grid.Column="1" />
<BoxView Color="Teal"
Grid.Row="1" />
<Label Text="Leftover space"
Grid.Row="1" Grid.Column="1"
TextColor="Purple"
BackgroundColor="Aqua"
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center" />
<Label Text="Span two rows (or more if you want)"
Grid.Column="2" Grid.RowSpan="2"
TextColor="Yellow"
BackgroundColor="Blue"
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center" />
<Label Text="Span two columns"
Grid.Row="2" Grid.ColumnSpan="2"
TextColor="Blue"
BackgroundColor="Yellow"
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center" />
<Label Text="Fixed 100x100"
Grid.Row="2" Grid.Column="2"
TextColor="Aqua"
BackgroundColor="Red"
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center" />
</Grid>
</ContentPage>
此 XAML 生成以下布局:
Grid.Row
、Grid.Column
、Grid.RowSpan
和 Grid.ColumnSpan
特性似乎是 Grid 类的属性,但此类不定义名为 Row
、Column
、RowSpan
或 ColumnSpan
的任何内容。 不过,Grid 类定义以下四个可绑定属性:RowProperty
、ColumnProperty
、RowSpanProperty
和 ColumnSpanProperty
,它们是称为附加属性的特殊类型的可绑定属性。 它们由 Grid 类定义,但设置在 Grid 的子级上。
注意
需要在代码中使用这些附加属性时,Grid 类提供以下静态方法:GetRow
、SetRow
、GetColumn
、SetColumn
、GetRowSpan
、SetRowSpan
、GetColumnSpan
和 SetColumnSpan
。
附加属性在 XAML 中可识别为包含一个类和一个属性名称(由句点分隔)的特性。 其名为附加属性是因为它们由一个类(在本例中为 Grid)定义但会附加到其他对象上(在本例中为 Grid 的子级)。 在布局期间,Grid 可以查询这些附加属性的值,以了解每个子级的放置位置。
内容属性
在前面的示例中,Grid 对象设置为 ContentPage 的 Content
属性。 但 XAML 中未引用 Content
属性,而可能是以下情况:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.XamlPlusCodePage"
Title="XAML + Code Page">
<ContentPage.Content>
<Grid>
...
</Grid>
</ContentPage.Content>
</ContentPage>
XAML 中不需要 Content
属性,因为所定义的要在 .NET MAUI XAML 中使用的元素可有一个属性指定为类上的 ContentProperty
特性:
[ContentProperty("Content")]
public class ContentPage : TemplatedPage
{
...
}
如果属性指定为类的 ContentProperty
,则意味着该属性不需要属性元素标记。 因此,上面的示例指定在开始和结束 ContentPage 标记之间显示的任何 XAML 内容都分配给 Content
属性。
许多类还具有 ContentProperty
特性定义。 例如,Label 的内容属性为 Text
。
平台差异
.NET MAUI 应用可以按平台自定义 UI 外观。 这可以在 XAML 中使用 OnPlatform
和 On
类来实现:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="...">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness">
<On Platform="iOS" Value="0,20,0,0" />
<On Platform="Android" Value="10,20,20,10" />
</OnPlatform>
</ContentPage.Padding>
...
</ContentPage>
OnPlatform
是泛型类,因此需要指定泛型类型参数,在本例中为 Thickness
(Padding
属性的类型)。 这是使用 x:TypeArguments
XAML 特性实现的。 OnPlatform
类定义一个 Default
属性,该属性可设置为将应用于所有平台的值:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="...">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness" Default="20">
<On Platform="iOS" Value="0,20,0,0" />
<On Platform="Android" Value="10,20,20,10" />
</OnPlatform>
</ContentPage.Padding>
...
</ContentPage>
在此示例中,Padding
属性在 iOS 和 Android 上设置为不同的值,在其他平台上设置为默认值。
OnPlatform
类还定义了一个 Platforms
属性,该属性是 On
对象的 IList
。 每个 On
对象均可设置 Platform
和 Value
属性以定义特定平台的 Thickness
值。 此外,On
的 Platform
属性为 IList<string>
类型,因此如果值相同,则可以包含多个平台:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="...">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness" Default="20">
<On Platform="iOS, Android" Value="10,20,20,10" />
</OnPlatform>
</ContentPage.Padding>
...
</ContentPage>
这是在 XAML 中设置依赖于平台的 Padding
属性的标准方法。
注意
如果 On
对象的 Value
属性不能用单个字符串表示,可以为其定义属性元素。
有关详细信息,请参阅根据平台自定义 UI 外观。
后续步骤
借助 .NET MAUI XAML 标记扩展,可以将属性设置为通过其他源间接引用的对象或值。 XAML 标记扩展对于共享对象和引用要在整个应用中使用的常量尤为重要。