XAML主要用于实例化和初始化对象。 但是,通常情况下,属性必须设置为复杂的对象,不能很容易地表示为XML字符串,有时由一个类定义的属性必须设置在子类上。 这两个需求需要属性元素和附加属性的基本XAML语法功能。
属性元素
在XAML中,类的属性通常设置为XML属性:
点击(此处)折叠或打开
- Label Text="Hello, XAML!"
- VerticalOptions="Center"
- FontAttributes="Bold"
- FontSize="Large"
- TextColor="Aqua" />
点击(此处)折叠或打开
- Label Text="Hello, XAML!"
- VerticalOptions="Center"
- FontAttributes="Bold"
- FontSize="Large" />
将空元素Label标签分离为开始标签和结束标签:
点击(此处)折叠或打开
- Label Text="Hello, XAML!"
- VerticalOptions="Center"
- FontAttributes="Bold"
- FontSize="Large">
-
- /Label>
在这些标签中,添加包含类名和由句点分隔的属性名的开始和结束标签:
点击(此处)折叠或打开
- Label Text="Hello, XAML!"
- VerticalOptions="Center"
- FontAttributes="Bold"
- FontSize="Large">
- Label.TextColor>
-
- /Label.TextColor>
- /Label>
将属性值设置为这些新标记的内容,如下所示:
点击(此处)折叠或打开
- Label Text="Hello, XAML!"
- VerticalOptions="Center"
- FontAttributes="Bold"
- FontSize="Large">
- Label.TextColor>
- Aqua
- /Label.TextColor>
- /Label>
用这个新的语法,可以引入一些方便的术语:
- 标签是一个对象元素。这是一个表示为XML元素的Xamarin.Forms对象。
- 文本,VerticalOptions,FontAttributes和FontSize是属性属性。它们是以XML属性表示的Xamarin.Forms属性。
- 在最后一个片段中,TextColor已经成为一个属性元素。这是一个Xamarin.Forms属性,但它现在是一个XML元素。
属性元素的定义可能首先看起来违反了XML语法,但事实并非如此。这段时间在XML中没有特别的意义。对于XML解码器来说,Label.TextColor只是一个普通的子元素。
然而,在XAML中,这个语法是非常特殊的。属性元素的规则之一就是Label.TextColor标签中不会出现任何其他内容。属性的值始终定义为属性元素开始和结束标记之间的内容。
您可以在多个属性上使用属性元素语法:
点击(此处)折叠或打开
- Label Text="Hello, XAML!"
- VerticalOptions="Center">
- Label.FontAttributes>
- Bold
- /Label.FontAttributes>
- Label.FontSize>
- Large
- /Label.FontSize>
- Label.TextColor>
- Aqua
- /Label.TextColor>
- /Label>
或者,您可以对所有属性使用属性元素语法:
点击(此处)折叠或打开
- Label>
- Label.Text>
- Hello, XAML!
- /Label.Text>
- Label.FontAttributes>
- Bold
- /Label.FontAttributes>
- Label.FontSize>
- Large
- /Label.FontSize>
- Label.TextColor>
- Aqua
- /Label.TextColor>
- Label.VerticalOptions>
- Center
- /Label.VerticalOptions>
- /Label>
但是,如果属性的值太复杂,无法用简单的字符串表示,则属性元素语法就变得非常重要。 在属性元素标签内,您可以实例化另一个对象并设置其属性。 例如,您可以使用属性设置将诸如VerticalOptions之类的属性显式设置为LayoutOptions值:
点击(此处)折叠或打开
- Label>
- ...
- Label.VerticalOptions>
- LayoutOptions Alignment="Center" />
- /Label.VerticalOptions>
- /Label>
以下是GridDemoPage类的XAML文件的开头,显示了RowDefinitions和ColumnDefinitions集合的属性元素标签:
点击(此处)折叠或打开
- ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
- 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.Row
- Grid.Column
这些属性的默认值为0.您还可以指示子项是否跨越具有以下属性的多个行或列:
- Grid.RowSpan
- Grid.ColumnSpan
这两个属性的默认值是1。
这是完整的GridDemoPage.xaml文件:
点击(此处)折叠或打开
- ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
- 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"
- Grid.Row="0" Grid.Column="0"
- TextColor="White"
- BackgroundColor="Blue" />
-
- BoxView Color="Silver"
- HeightRequest="0"
- Grid.Row="0" Grid.Column="1" />
-
- BoxView Color="Teal"
- Grid.Row="1" Grid.Column="0" />
-
- 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.Row="0" Grid.Column="2" Grid.RowSpan="2"
- TextColor="Yellow"
- BackgroundColor="Blue"
- HorizontalTextAlignment="Center"
- VerticalTextAlignment="Center" />
-
- Label Text="Span two columns"
- Grid.Row="2" Grid.Column="0" 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>
以下是所有三个平台的外观:
仅仅从语法判断,Grid.Row,Grid.Column,Grid.RowSpan和Grid.ColumnSpan属性看起来都是Grid的静态字段或属性,但有趣的是,Grid并没有定义任何名为Row,Column,RowSpan,或ColumnSpan。
相反,Grid定义了四个名为RowProperty,ColumnProperty,RowSpanProperty和ColumnSpanProperty的可绑定属性。这些是被称为附加属性的特殊类型的可绑定属性。它们由网格类定义,但是设置在网格的子节点上。
当您希望在代码中使用这些附加属性时,Grid类将提供名为SetRow,GetColumn等静态方法。但是在XAML中,这些附加的属性使用简单的属性名称在网格的子元素中设置为属性。
附加属性在XAML文件中始终可识别为属性,其中包含由句点分隔的类和属性名称。它们被称为附加属性,因为它们是由一个类(在这种情况下为网格)定义的,但是附加到其他对象(在这种情况下是网格的子节点)。在布局过程中,网格可以询问这些附加属性的值,以知道每个孩子的放置位置。
AbsoluteLayout类定义了两个名为LayoutBounds和LayoutFlags的附加属性。以下是使用AbsoluteLayout的比例定位和尺寸特征实现的棋盘图案:
点击(此处)折叠或打开
- ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
- xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
- x:Class="XamlSamples.AbsoluteDemoPage"
- Title="Absolute Demo Page">
-
- AbsoluteLayout BackgroundColor="#FF8080">
- BoxView Color="#8080FF"
- AbsoluteLayout.LayoutBounds="0.33, 0, 0.25, 0.25"
- AbsoluteLayout.LayoutFlags="All" />
-
- BoxView Color="#8080FF"
- AbsoluteLayout.LayoutBounds="1, 0, 0.25, 0.25"
- AbsoluteLayout.LayoutFlags="All" />
-
- BoxView Color="#8080FF"
- AbsoluteLayout.LayoutBounds="0, 0.33, 0.25, 0.25"
- AbsoluteLayout.LayoutFlags="All" />
-
- BoxView Color="#8080FF"
- AbsoluteLayout.LayoutBounds="0.67, 0.33, 0.25, 0.25"
- AbsoluteLayout.LayoutFlags="All" />
-
- BoxView Color="#8080FF"
- AbsoluteLayout.LayoutBounds="0.33, 0.67, 0.25, 0.25"
- AbsoluteLayout.LayoutFlags="All" />
-
- BoxView Color="#8080FF"
- AbsoluteLayout.LayoutBounds="1, 0.67, 0.25, 0.25"
- AbsoluteLayout.LayoutFlags="All" />
-
- BoxView Color="#8080FF"
- AbsoluteLayout.LayoutBounds="0, 1, 0.25, 0.25"
- AbsoluteLayout.LayoutFlags="All" />
-
- BoxView Color="#8080FF"
- AbsoluteLayout.LayoutBounds="0.67, 1, 0.25, 0.25"
- AbsoluteLayout.LayoutFlags="All" />
-
- /AbsoluteLayout>
- /ContentPage>
对于这样的事情,你可能会质疑使用XAML的智慧。 当然,LayoutBounds矩形的重复性和规律性表明在代码中可能会更好地实现。
这当然是合理的问题,在定义用户界面时平衡代码和标记的使用是没有问题的。 在XAML中定义一些视觉效果很容易,然后使用代码隐藏文件的构造函数添加一些可能在循环中更好地生成的视觉效果。
内容属性
在前面的示例中,将StackLayout,Grid和AbsoluteLayout对象设置为ContentPage的Content属性,这些布局的子项实际上是Children集合中的项目。 然而,这些内容和儿童的属性是在XAML文件无处。
您当然可以包含Content和Children属性作为属性元素,例如在XamlPlusCode示例中:
点击(此处)折叠或打开
- ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
- xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
- x:Class="XamlSamples.XamlPlusCodePage"
- Title="XAML + Code Page">
- ContentPage.Content>
- StackLayout>
- StackLayout.Children>
- Slider VerticalOptions="CenterAndExpand"
- ValueChanged="OnSliderValueChanged" />
-
- Label x:Name="valueLabel"
- Text="A simple Label"
- FontSize="Large"
- HorizontalOptions="Center"
- VerticalOptions="CenterAndExpand" />
-
- Button Text="Click Me!"
- HorizontalOptions="Center"
- VerticalOptions="CenterAndExpand"
- Clicked="OnButtonClicked" />
- /StackLayout.Children>
- /StackLayout>
- /ContentPage.Content>
- /ContentPage>
用于XAML的Xamarin.Forms中定义的元素允许在类的ContentProperty属性中标记一个属性。 如果您查看在线Xamarin.Forms文档中的ContentPage类,您将看到以下属性:
点击(此处)折叠或打开
- [Xamarin.Forms.ContentProperty("Content")]
- public class ContentPage : TemplatedPage
StackLayout,Grid,AbsoluteLayout和RelativeLayout都来自Layout ,如果你在Xamarin.Forms文档中查找Layout ,你会看到另一个ContentProperty属性:
点击(此处)折叠或打开
- [Xamarin.Forms.ContentProperty("Children")]
- public abstract class LayoutT> : Layout ...
其他类也有ContentProperty属性定义。 例如,标签的内容属性是文本。 检查他人的API文档。
平台与OnPlatform的区别
在单页面应用程序中,通常在页面上设置Padding属性以避免覆盖iOS状态栏。 在代码中,您可以使用Device.RuntimePlatform属性来达到此目的:
点击(此处)折叠或打开
- if (Device.RuntimePlatform == Device.iOS)
- {
- Padding = new Thickness(0, 20, 0, 0);
- }
点击(此处)折叠或打开
- ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
- xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
- x:Class="...">
-
- ContentPage.Padding>
-
- /ContentPage.Padding>
- ...
- /ContentPage>
在这些标签中,包含一个OnPlatform标签。 OnPlatform是一个通用类。 您需要指定泛型类型参数,在这种情况下,厚度是Padding属性的类型。 幸运的是,有一个XAML属性专门用来定义一个名为x:TypeArguments的泛型参数。 这应该与您正在设置的属性的类型匹配:
点击(此处)折叠或打开
- ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
- xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
- x:Class="...">
-
- ContentPage.Padding>
- OnPlatform x:TypeArguments="Thickness">
-
- /OnPlatform>
- /ContentPage.Padding>
- ...
- /ContentPage>
点击(此处)折叠或打开
- ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
- xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
- x:Class="...">
-
- ContentPage.Padding>
- OnPlatform x:TypeArguments="Thickness">
- OnPlatform.Platforms>
-
- /OnPlatform.Platforms>
- /OnPlatform>
- /ContentPage.Padding>
- ...
- /ContentPage>
点击(此处)折叠或打开
- ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
- xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
- x:Class="...">
-
- ContentPage.Padding>
- OnPlatform x:TypeArguments="Thickness">
- OnPlatform.Platforms>
- On Platform="iOS" Value="0, 20, 0, 0" />
- On Platform="Android" Value="0, 0, 0, 0" />
- On Platform="UWP" Value="0, 0, 0, 0" />
- /OnPlatform.Platforms>
- /OnPlatform>
- /ContentPage.Padding>
- ...
- /ContentPage>
点击(此处)折叠或打开
- ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
- 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="0, 0, 0, 0" />
- On Platform="UWP" Value="0, 0, 0, 0" />
- /OnPlatform>
- /ContentPage.Padding>
- ...
- /ContentPage>
点击(此处)折叠或打开
- ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
- 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, UWP" Value="0, 0, 0, 0" />
- /OnPlatform>
- /ContentPage.Padding>
- ...
- /ContentPage>
点击(此处)折叠或打开
- ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
- 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" />
- /OnPlatform>
- /ContentPage.Padding>
- ...
- /ContentPage>
点击(此处)折叠或打开
- ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
- xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
- x:Class="...">
-
- ContentPage.Padding>
- OnPlatform x:TypeArguments="Thickness">
- On Platform="iOS">
- On.Value>
- 0, 20, 0, 0
- /On.Value>
- /On>
- /OnPlatform>
- /ContentPage.Padding>
- ...
- /ContentPage>
概要
通过属性元素和附加属性,许多基本的XAML语法已经建立。 但是,有时您需要以间接方式(例如从资源字典中)将属性设置为对象。 这个方法在下一部分,第3部分中有介绍。XAML标记扩展。