學習目標
- x:Static - XAML 類 C# 再來一發
- Resource - StaticResource - 可重複利用的擴充標籤
Xamarin 一直積極的要讓 XAML 做一些 C# 能做的事情,例如這一章節要講的擴充標籤 (markup extensions)。
在 C# 內要指派給 triangle.Angle1 值的話可以如下:
在 C# 內要指派給 triangle.Angle1 值的話可以如下:
triangle.Angle1 = 45;
triangle.Angle1 = 180 * radians / Math.PI;
triangle.Angle1 = angles[i];
triangle.Angle1 = animator.GetCurrentAngle();
只要 結果回傳 是浮點數 (double) 就好。
但你沒辦法在 XAML 內寫上這種鬼東西的:
<triangle.Angle1>
180 * radians / Math.PI
</triangle.Angle1>
讓哥懷念起 MVC 的 Razor 真是方便...鑒於以上原因,Xamarin 在 XAML 2009 規格內定義了 擴充標籤 (markup extensions),讓我們在編寫 XAML 時能有更多的彈性。
擴充標籤有以下三大類型:
1. 前面帶 x : 的擴充標籤:
- x : Static
- x : Reference
- x : Type
- x : Null
- x : Array
2. 跟資料面有關係的:
- StaticResource
- DynamicResource
- Binding
3. 或是給 RelativeLayout 用的:
- ConstrainExpression
從第一個 x:Static 來介紹 -
x:Static
<Label Text="Just some text" BackgroundColor="Accent" TextColor="Black" FontAttributes="Italic" VerticalOptions="Center" HorizontalTextAlignment="Center" />
Label 的五個屬性值都是 字串 ,
其實執行時,這些字串都是先透過 C # 的 TryParse (轉換) 後才給予他們真正的意義。
可以使用 x:Static 改寫成:
<Label Text="Just some text" BackgroundColor="{x:Static Color.Accent}" TextColor="{x:Static Color.Black}" FontAttributes="{x:Static FontAttributes.Italic}" VerticalOptions="{x:Static LayoutOptions.Center}" HorizontalTextAlignment="{x:Static TextAlignment.Center}" />
這兩個比較下來很清楚的知道 x:Static 的功能,就是在 XAML 內使用 C# 的變數。
但以上的改寫其實沒啥意義...
介紹有用一點的程式,我們可以先在 C# 定義好變數和其值:
namespace SharedStatics { static class AppConstants { public static Color LightBackground = Color.Yellow; public static Color DarkForeground = Color.Blue; public static double NormalFontSize = 18; public static double TitleFontSize = 1.4 * NormalFontSize; public static double ParagraphSpacing = 10; public const FontAttributes Emphasis = FontAttributes.Italic; public const FontAttributes TitleAttribute = FontAttributes.Bold; public const TextAlignment TitleAlignment = TextAlignment.Center; } }
接著在 XAML 內使用其變數:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:SharedStatics" x:Class="SharedStatics.SharedStaticsPage" BackgroundColor="{x:Static local:AppConstants.LightBackground}"> <StackLayout Padding="10, 0" Spacing="{x:Static local:AppConstants.ParagraphSpacing}">
要注意的是在 ContentPage 內有先引用 xmlns:local="clr-namespace:SharedStatics"。
另外,因為 Math 和 Enviroment 在 .NET System namespace 內有定義,可以在引用 namespace 後使用其靜態變數如 Math.PI:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" x:Class="SystemStatics.SystemStaticsPage"> <!--Math.PI--> <Button Text=" Button with π border width " BorderWidth="{x:Static sys:Math.PI}" HorizontalOptions="Center" VerticalOptions="CenterAndExpand"> <Button.BackgroundColor> <OnPlatform x:TypeArguments="Color" Android="#404040" /> </Button.BackgroundColor> <Button.BorderColor> <OnPlatform x:TypeArguments="Color" Android="White" WinPhone="Black" /> </Button.BorderColor> </Button> <Label VerticalOptions="CenterAndExpand" HorizontalTextAlignment="Center" FontSize="Medium"> <!--Environment.NewLine--> <Label.FormattedText> <FormattedString> <Span Text="Three lines of text" /> <Span Text="{x:Static sys:Environment.NewLine}" /> <Span Text="separated by" /> <Span Text="{x:Static sys:Environment.NewLine}" /> <Span Text="Environment.NewLine" FontSize="Medium" FontAttributes="Italic" /> <Span Text=" strings" /> </FormattedString> </Label.FormattedText> </Label> </StackLayout> </ContentPage>
執行結果:
Resource dictionaries
上面看到 C# 內建立全域變數,並在 XAML 內使用其值的範例。
Xamarin 也想將這件事情搬來 XAML 做 ... 所以提供了 <ResourceDictionary> 這樣的擴充標籤,讓我們在 XAML 內建立共用的變數資源。
使用 Resource dictionaries 時又分成 StaticResource 和 DynamicResource,差在一個讀取靜態XAML dictionaries,後一個由 .cs 指派 dictionaries 時使用。
StaticResource
假設你要在 StackLayout 內建立三個相似的 Button,你可能會這麼寫:
<StackLayout> <!--First Button--> <Button Text=" Carpe diem " HorizontalOptions="Center" VerticalOptions="CenterAndExpand" BorderWidth="3" TextColor="Red" FontSize="Large"> <Button.BackgroundColor> <OnPlatform x:TypeArguments="Color" Android="#404040" /> </Button.BackgroundColor> <Button.BorderColor> <OnPlatform x:TypeArguments="Color" Android="White" WinPhone="Black" /> </Button.BorderColor> </Button> <!--Second Button--> <Button Text=" Sapere aude " HorizontalOptions="Center" VerticalOptions="CenterAndExpand" BorderWidth="3" TextColor="Red" FontSize="Large"> <Button.BackgroundColor> <OnPlatform x:TypeArguments="Color" Android="#404040" /> </Button.BackgroundColor> <Button.BorderColor> <OnPlatform x:TypeArguments="Color" Android="White" WinPhone="Black" /> </Button.BorderColor> </Button> <!--Third Button--> <Button Text=" Discere faciendo " HorizontalOptions="Center" VerticalOptions="CenterAndExpand" BorderWidth="3" TextColor="Red" FontSize="Large"> <Button.BackgroundColor> <OnPlatform x:TypeArguments="Color" Android="#404040" /> </Button.BackgroundColor> <Button.BorderColor> <OnPlatform x:TypeArguments="Color" Android="White" WinPhone="Black" /> </Button.BorderColor> </Button> </StackLayout>
很多屬性的值是 重複 的,執行結果如下:
此時我們就能在 (Visual Elements).Resource 內撰寫 <ResourceDictionoary> 標籤,來製作 可重複利用 的資源檔:
<ContentPage.Resources> <ResourceDictionary> <LayoutOptions x:Key="horzOptions">Center</LayoutOptions> <LayoutOptions x:Key="vertOptions" Alignment="Center" Expands="True" /> <x:Double x:Key="borderWidth">3</x:Double> <Color x:Key="textColor">Red</Color> <OnPlatform x:Key="backgroundColor" x:TypeArguments="Color" Android="#404040" /> <OnPlatform x:Key="borderColor" x:TypeArguments="Color" Android="White" WinPhone="Black" /> <x:String x:Key="fontSize">Large</x:String> </ResourceDictionary> </ContentPage.Resources>要注意 ResourceDictionary 內每個資源都有 x:Key 這屬性,且同一層級下的 x:Key 不能重複。
接著使用 StaticResource 改寫屬性值:
<Button Text=" Discere faciendo " HorizontalOptions="{StaticResource horzOptions}" VerticalOptions="{StaticResource vertOptions}" BorderWidth="{StaticResource borderWidth}" TextColor="{StaticResource textColor}" BackgroundColor="{StaticResource backgroundColor}" BorderColor="{StaticResource borderColor}" FontSize="{StaticResource fontSize}" />
這樣三顆 Button 重複的屬性值,我們只要在 ResourceDictionary 寫一次就能使用,當然也便於維護。
Resource 可以儲存各種物件,像是把一顆 Button 放進去:
<ContentPage.Resources> <ResourceDictionary> <Button x:Key="button" Text="Shared Button?" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" FontSize="Large" /> </ResourceDictionary> </ContentPage.Resources>
但是!!! 同一顆按鈕是不能出現兩次的… 所以以下寫法會出錯:
<StackLayout> <StaticResourceExtension Key="button" /> <StaticResourceExtension Key="button" /> </StackLayout>
關於這種多個元件需要同樣的 屬性 時,會在 12章 Style 有說明。
沒有留言:
張貼留言
注意:只有此網誌的成員可以留言。