基本 XAML 语法

Browse sample. 浏览示例

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 对象。
  • TextVerticalOptionsFontAttributesFontSize 是属性特性。 它们是以 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 布局具有名为 RowDefinitionsColumnDefinitions 的属性,它们的类型分别为 RowDefinitionCollectionColumnDefinitionCollection。 这些类型是 RowDefinitionColumnDefinition 对象的集合,通常使用属性元素语法进行设置:

<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 需要 RowDefinitionsColumnDefinitions 集合的属性元素来定义行和列。 这表明必须有一种方法来指示 Grid 的每个子级所在的行和列。

Grid 的每个子级的标记中,使用 Grid.RowGrid.Column 特性(默认值为 0)指定该子级的行和列。 还可以使用 Grid.RowSpanGrid.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 生成以下布局:

.NET MAUI Grid layout.

Grid.RowGrid.ColumnGrid.RowSpanGrid.ColumnSpan 特性似乎是 Grid 类的属性,但此类不定义名为 RowColumnRowSpanColumnSpan 的任何内容。 不过,Grid 类定义以下四个可绑定属性:RowPropertyColumnPropertyRowSpanPropertyColumnSpanProperty,它们是称为附加属性的特殊类型的可绑定属性。 它们由 Grid 类定义,但设置在 Grid 的子级上。

注意

需要在代码中使用这些附加属性时,Grid 类提供以下静态方法:GetRowSetRowGetColumnSetColumnGetRowSpanSetRowSpanGetColumnSpanSetColumnSpan

附加属性在 XAML 中可识别为包含一个类和一个属性名称(由句点分隔)的特性。 其名为附加属性是因为它们由一个类(在本例中为 Grid)定义但会附加到其他对象上(在本例中为 Grid 的子级)。 在布局期间,Grid 可以查询这些附加属性的值,以了解每个子级的放置位置。

内容属性

在前面的示例中,Grid 对象设置为 ContentPageContent 属性。 但 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 中使用 OnPlatformOn 类来实现:

<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 是泛型类,因此需要指定泛型类型参数,在本例中为 ThicknessPadding 属性的类型)。 这是使用 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 对象均可设置 PlatformValue 属性以定义特定平台的 Thickness 值。 此外,OnPlatform 属性为 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 标记扩展对于共享对象和引用要在整个应用中使用的常量尤为重要。