學習目標
- DynamicResource
- ResourceDictionary 的階層制
- 客製化擴充標籤
延續上一小節的 Resource,除了 StaticResource 外,還有一個 DynamicResource,顧名思義就是要顯示動態資訊的資源檔,而最常見的動態資料就是時間。
直接來看程式,我們先在 C# 設定好 Resource,其值每秒都會更改:
接著 XAML 內分別對兩個 Label 使用 StaticResource 和 DyanaicResource:
再看結果就會發現差異了:
第二個用 DynamicResource 的 Label 會持續顯示當時的時間,第一個 StaticResource 則維持 XAML 給予的預設值。
Dictionaries 的階層
這邊有個很重要的觀念,設定 Dictionary 時,key 都是不能重複的。
直接來看程式,我們先在 C# 設定好 Resource,其值每秒都會更改:
public partial class DynamicVsStaticPage : ContentPage { public DynamicVsStaticPage() { InitializeComponent(); Device.StartTimer(TimeSpan.FromSeconds(1), () => { Resources["currentDateTime"] = DateTime.Now.ToString(); return true; }); } }
接著 XAML 內分別對兩個 Label 使用 StaticResource 和 DyanaicResource:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="DynamicVsStatic.DynamicVsStaticPage" Padding="5, 0"> <!--Resources--> <ContentPage.Resources> <ResourceDictionary> <x:String x:Key="currentDateTime">Not actually a DateTime</x:String> </ResourceDictionary> </ContentPage.Resources> <StackLayout> <Label Text="StaticResource on Label.Text:" VerticalOptions="EndAndExpand" FontSize="Medium" /> <!--StaticResource--> <Label Text="{StaticResource currentDateTime}" VerticalOptions="StartAndExpand" HorizontalTextAlignment="Center" FontSize="Medium" /> <Label Text="DynamicResource on Label.Text:" VerticalOptions="EndAndExpand" FontSize="Medium" /> <!--DynamicResource--> <Label Text="{DynamicResource currentDateTime}" VerticalOptions="StartAndExpand" HorizontalTextAlignment="Center" FontSize="Medium" /> </StackLayout> </ContentPage>
再看結果就會發現差異了:
第二個用 DynamicResource 的 Label 會持續顯示當時的時間,第一個 StaticResource 則維持 XAML 給予的預設值。
Dictionaries 的階層
這邊有個很重要的觀念,設定 Dictionary 時,key 都是不能重複的。
但 !
XAML 允許一種例外,當 ResourceDictionary 在不同階層時能出現重複的 key。
舉例來說,
這支程式碼內有兩組 ResourceDictionary,一組在 ContentPage,另一組在 StackLayout,都具有相同的 key - textColor
加入三顆 Button 來觀察資源檔的階層關係。
*OnPlatform 寫法已更改,請參考此篇文章
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="ResourceTrees.ResourceTreesPage"> <!--ContentPage Resources--> <ContentPage.Resources> <ResourceDictionary> <LayoutOptions x:Key="horzOptions">Center</LayoutOptions> <LayoutOptions x:Key="vertOptions" Alignment="Center" Expands="True" /> <!--x:Key textColor--> <OnPlatform x:Key="textColor" x:TypeArguments="Color" iOS="Red" Android="Pink" WinPhone="Blue" /> </ResourceDictionary> </ContentPage.Resources> <StackLayout> <Button Text=" Carpe diem " HorizontalOptions="{StaticResource horzOptions}" VerticalOptions="{StaticResource vertOptions}" BorderWidth="{StaticResource borderWidth}" TextColor="{StaticResource textColor}" BackgroundColor="{StaticResource backgroundColor}" BorderColor="{StaticResource borderColor}" FontSize="{StaticResource fontSize}" /> <StackLayout> <!--StackLayout Resources--> <StackLayout.Resources> <ResourceDictionary> <!--x:Key textColor--> <Color x:Key="textColor">Default</Color> <x:String x:Key="fontSize">Default</x:String> </ResourceDictionary> </StackLayout.Resources> <Button Text=" Sapere aude " HorizontalOptions="{StaticResource horzOptions}" BorderWidth="{StaticResource borderWidth}" TextColor="{StaticResource textColor}" BackgroundColor="{StaticResource backgroundColor}" BorderColor="{StaticResource borderColor}" FontSize="{StaticResource fontSize}" /> </StackLayout> <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}" /> </StackLayout> </ContentPage>
執行結果,可以發現中間的按鈕採用的是 StackeLayout 內的 ResourceDictionary。
元件會選擇引用離自己最近的資源檔。
客製化 markup extension
最後這小節教你如何製作屬於自己的擴充標籤,底下範例製作一個 HslColor 的標籤:
using System; using Xamarin.Forms; using Xamarin.Forms.Xaml; namespace Xamarin.FormsBook.Toolkit { public class HslColorExtension : IMarkupExtension { public HslColorExtension() { A = 1; } public double H { set; get; } public double S { set; get; } public double L { set; get; } public double A { set; get; } public object ProvideValue(IServiceProvider serviceProvider) { return Color.FromHsla(H, S, L, A); } } }
要注意類別的 命名方式 和 繼承了 IMarkupExtension 這介面,一定要實作 ProvideValue 這方法並回傳值。
接著確保 PCL 的引用,先在 App 內初始化:
namespace CustomExtensionDemo { public class App : Application { public App() { Xamarin.FormsBook.Toolkit.Toolkit.Init(); MainPage = new CustomExtensionDemoPage(); } … } }
接著來看 XAML 如何使用,同樣注意最上方 toolkit 的引用:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:toolkit= "clr-namespace:Xamarin.FormsBook.Toolkit;assembly=Xamarin.FormsBook.Toolkit" x:Class="CustomExtensionDemo.CustomExtensionDemoPage"> <StackLayout> <!-- Red --> <BoxView HorizontalOptions="Center" VerticalOptions="CenterAndExpand"> <BoxView.Color> <toolkit:HslColorExtension H="0" S="1" L="0.5" /> </BoxView.Color> </BoxView> <!-- Green --> <BoxView HorizontalOptions="Center" VerticalOptions="CenterAndExpand"> <BoxView.Color> <toolkit:HslColorExtension H="0.33" S="1" L="0.5" /> </BoxView.Color> </BoxView> <!-- Blue --> <BoxView Color="{toolkit:HslColor H=0.67, S=1, L=0.5}" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" /> <!-- Gray --> <BoxView Color="{toolkit:HslColor H=0, S=0, L=0.5}" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" /> <!-- Semitransparent white --> <BoxView Color="{toolkit:HslColor H=0, S=0, L=1, A=0.5}" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" /> <!-- Semitransparent black --> <BoxView Color="{toolkit:HslColor H=0, S=0, L=0, A=0.5}" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" /> </StackLayout> </ContentPage>
執行結果:
請問,
回覆刪除這一行Xamarin.FormsBook.Toolkit.Toolkit.Init();
會說找不到 FromsBook 這個 namespace,不過檔案我有照原文書建了,這是什麼問題?
謝謝
沒看到你的程式碼我也很難判定,如果確定
刪除namespace Xamarin.FormsBook.Toolkit
{
public class HslColorExtension : IMarkupExtension
{
...
都沒問題也存在於專案內,那試著把專案清除重建看看
試出來了,專案的參考沒有把Xamarin.FormsBook.Toolkit加進來,所以不能用
刪除感謝
羅根大大
回覆刪除我想請問
public object ProvideValue(IServiceProvider serviceProvider)
{
return Color.FromHsla(H, S, L, A);
}
在何時會被執行,是在xaml帶入參數後嗎??
是因為IServiceProvider serviceProvider的關係嗎??
感謝
對喔,
刪除以 Xamarin 的角度來說,會先把 XAML 轉成 C#,
所以擴充標籤也只是逐步去執行先寫好的副程式而已