内容属性特性
ScaryColorList程序中的XAML文件实际上比它需要的时间稍长。 您可以删除ContentPage.Content标签,所有StackLayout.Children标签和所有Frame.Content标签,并且程序的工作原理是相同的:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ScaryColorList.ScaryColorListPage">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness"
iOS="0, 20, 0, 0" />
</ContentPage.Padding>
<StackLayout>
<Frame OutlineColor="Accent">
<StackLayout Orientation="Horizontal">
<BoxView Color="Red" />
<Label Text="Red"
VerticalOptions="Center" />
</StackLayout>
</Frame>
<Frame OutlineColor="Accent">
<StackLayout Orientation="Horizontal">
<BoxView Color="Green" />
<Label Text="Green"
VerticalOptions="Center" />
</StackLayout>
</Frame>
<Frame OutlineColor="Accent">
<StackLayout Orientation="Horizontal">
<BoxView Color="Blue" />
<Label Text="Blue"
VerticalOptions="Center" />
</StackLayout>
</Frame>
</StackLayout>
</ContentPage>
它现在看起来很干净。 剩下的唯一属性元素是ContentPage的Padding属性。
与几乎所有关于XAML语法的内容一样,某些属性元素的消除是由底层类支持的。 XAML中使用的每个类都被允许将一个属性定义为一个隐含属性(有时也称为该类的默认属性)。 对于此内容属性,不需要属性元素标记,并且开始和结束标记内的任何XML内容都会自动分配给此属性。 非常方便,ContentPage的内容属性是Content,StackLayout的内容属性是Children,Frame的content属性是Content。
这些内容属性被记录下来,但你需要知道在哪里看。 一个类通过使用ContentPropertyAttribute来指定其内容属性。 如果该属性附加到一个类中,它将与类声明一起出现在联机Xamarin.Forms API文档中。 以下是它在ContentPage文档中的显示方式:
[Xamarin.Forms.ContentProperty("Content")]
public class ContentPage : TemplatedPage
如果你大声说出来,这听起来有点多余:Content属性是ContentPage的内容属性。
Frame类的声明类似于:
[Xamarin.Forms.ContentProperty("Content")]
public class Frame : ContentView
StackLayout没有应用ContentProperty特性,但StackLayout派生自Layout ,Layout 具有ContentProperty特性:
[Xamarin.Forms.ContentProperty("Children")]
public abstract class Layout<T> : Layout, IViewContainer<T>
where T : View
ContentProperty特性由派生自Layout 的类继承,所以Children是StackLayout的内容属性。
当然,如果您在不需要时包含属性元素,则没有问题,但在大多数情况下,它们将不再出现在本书的示例程序中。
格式化文本
由XAML文件显示的文本可能只涉及一两个单词,但有时需要整个段落,可能是一些嵌入式字符格式。 在XAML中指定字符格式并不总是那么明显,或者很容易,因为我们熟悉HTML。
TextVariations解决方案具有一个XAML文件,该文件在可滚动的StackLayout中包含七个Label视图:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TextVariations.TextVariationsPage">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness"
iOS="0, 20, 0, 0" />
</ContentPage.Padding>
<ScrollView>
<StackLayout>
</StackLayout>
</ScrollView>
</ContentPage>
七个标签视图中的每一个都显示了定义显示文本的不同方式。 出于参考目的,这里是在所有三个平台上运行的程序:
最简单的方法只需要在Label元素的Text属性中设置几个字:
<Label VerticalOptions="CenterAndExpand"
Text="Single lines of text are easy." />
您也可以通过将Text属性分解为属性元素来设置Text属性:
<Label VerticalOptions="CenterAndExpand">
<Label.Text>
Text can also be content of the Text property.
</Label.Text>
</Label>
Text是Label的内容属性,所以你不需要Label.Text标签:
<Label VerticalOptions="CenterAndExpand">
Text is the content property of Label.
</Label>
当您将文本设置为标签的内容(不管您是否使用Label.Text标签)时,文本将被裁剪:从文本的开头和结尾删除包括回车符在内的所有空白字符。 但是,所有嵌入的空白都会保留,包括行尾字符。
将Text属性设置为属性属性时,引号内的所有空白都会保留,但如果文本占用XAML文件中的多行,则每行尾字符(或字符序列)都将转换为 一个空间。
因此,显示一个统一格式的文本的整个段落有些问题。 最简单的方法是将文本设置为属性属性。 您可以将整个段落放在XAML文件中作为一行,但如果您更喜欢使用多行,则应该在由引号包围的XAML文件中将整个图形对齐,如下所示:
<Label VerticalOptions="CenterAndExpand"
Text=
"Perhaps the best way to define a paragraph of
uniformly formatted text is by setting the Text
property as an attribute and left justifying
the block of text in the XAML file. End-of-line
characters are converted to a space character." />
行尾字符被转换为空格字符,因此各行都被适当地关联。 但要小心:不要将任何流浪的角色留在单行的末尾或开头。 这些将在该段落中显示为无关字符。
当多行文本被指定为标签的内容时,仅在文本的开始和结尾处的空白被裁剪。 所有嵌入的空白都会保留,包括行尾字符:
<Label VerticalOptions="CenterAndExpand">
Text as content has the curse
Of breaks at each line's close.
That's a format great for verse
But not the best for prose.
</Label>
该文本呈现为四行。 如果您在Xamarin.Forms应用程序中显示列表或诗歌,那正是您想要的。 否则,可能不会。
如果您的行或段落文本需要某些不一致的段落格式,则您需要使用Label的FormattedText属性。 您可能还记得,您将其设置为FormattedString对象,然后将多个Span对象设置为FormattedString的Spans集合。 在XAML中,您需要Label.FormattedString的property-element标签,但是Spans是FormattedString的内容属性:
<Label VerticalOptions="CenterAndExpand">
<Label.FormattedText>
<FormattedString>
<Span Text="A single line with " />
<Span Text="bold" FontAttributes="Bold" />
<Span Text=" and " />
<Span Text="italic" FontAttributes="Italic" />
<Span Text=" and " />
<Span Text="large" FontSize="Large" />
<Span Text=" text." />
</FormattedString>
</Label.FormattedText>
</Label>
请注意,非格式化项目的文本属性在文本字符串的末尾或开头处有空格,或两者都有,因此这些项目不会彼此碰撞。
但是,在一般情况下,您可能正在处理整个段落。 您可以将Span的Text属性设置为长行,或者可以将其包装在多行上。 与标签一样,将整个块保留在XAML文件中左对齐:
<Label VerticalOptions="CenterAndExpand">
<Label.FormattedText>
<FormattedString>
<Span Text=
"A paragraph of formatted text requires left justifying
it within the XAML file. But the text can include multiple
kinds of character formatting, including " />
<Span Text="bold" FontAttributes="Bold" />
<Span Text=" and " />
<Span Text="italic" FontAttributes="Italic" />
<Span Text=" and " />
<Span Text="large" FontSize="Large" />
<Span Text=
" and whatever combinations you might desire to adorn
your glorious prose." />
</FormattedString>
</Label.FormattedText>
</Label>
您会在截图中注意到,具有较大字体大小的文本与基线上的常规文本对齐,这是印刷适当的方法,并调整了行间距以适应较大的文本。
在大多数Xamarin.Forms程序中,XAML和代码都不是孤立存在,而是一起工作。 XAML中的元素可以触发代码中处理的事件,代码可以修改XAML中的元素。 在下一章中,你会看到这是如何工作的。