XAML 標記延伸
- 10 分鐘
大部分的 XAML 定義將在編譯期間才會決定。 您通常應該會知道元素的位置、使用的色彩與字型,以及要指派給屬性的常值。
不過,在某些時候您會需要對無法在編譯期間決定的值,設定其屬性值。 這些值通常必須在程式執行時才能得知。 在這些情況下,您可以先建立一個會在執行階段提供值給 XAML 的物件。 XAML 為此支援 標記延伸 。
在此單元中,您會了解如何建立和使用標記延伸。
什麼是標記延伸?
標記延伸是一個類別,可在 XAML 中用來存取執行階段值。 假設在 XAML UI 中已定義了許多標籤,而您想要將 FontSize 屬性設定為在整個應用程式中具有相同的值,藉以確保所有標籤樣式都維持一致。 您可以使用 XAML 來設定 FontSize 屬性,如以下範例所示:
<Label Text="Hello, World!"
Grid.Row="0"
SemanticProperties.HeadingLevel="Level1"
FontSize="28"
HorizontalOptions="CenterAndExpand"/>
您可以針對每一個標籤重複這個設定步驟,但如果稍後想要變更此值的話,該怎麼辦? 您需要找到這個屬性的每一個執行個體,並進行變更。 此外,假設您不知道該使用什麼值;您可以依據像是裝置方向、螢幕解析度或其他考量,來計算執行階段值。 在這些情況下,您會需要比硬式編碼常值更為精細的資訊。 這正是標記延伸的實用之處。 標記延伸可讓您更靈活地取得會被用於 XAML 中的值。
建立標記延伸
標記延伸是實作 Microsoft.Maui.Controls.Xaml.IMarkupExtension 介面的 類別。 這個介面定義了一種名為 ProvideValue 的方法,其中包含下列特徵標記:
public object ProvideValue(IServiceProvider serviceProvider)
{
...
}
此方法的目的是要提供一個值給 XAML 標記。 請注意,傳回型別為 object,所以此值可以為任何型別,只要適合使用該值的位置即可。 例如,在計算並傳回字型大小的標記延伸中,傳回類型應該是 double。
serviceProvider 參數包含有關標記延伸在 XAML 程式碼中使用位置的資訊;與其他資訊不同的是,它可以識別要套用延伸的控制項。
您可以讓 FontSize 屬性的標記延伸保持簡單。 在下列範例中,MainPage 類別會公開名為 MyFontSize 的 double 欄位。 GlobalFontSizeExtension 類別會實作 IMarkupExtension 介面,而 ProvideValue 方法會傳回 MyFontSize 變數的值:
namespace MyMauiApp;
public partial class MainPage : ContentPage
{
public const double MyFontSize = 28;
public MainPage()
{
InitializeComponent();
...
}
...
}
public class GlobalFontSizeExtension : IMarkupExtension
{
public object ProvideValue(IServiceProvider serviceProvider)
{
return MainPage.MyFontSize;
}
}
注意
MyFontSize 欄位必須是 MainPage 類別的 static 成員,才能以這種方式在 ProvideValue 方法中加以參照。 良好做法表示在此情況下,變數應該也是常數。 const 值為 static。
根據方向和裝置的外形規格等因素,ProvideValue 方法也可以對傳回的值加以調整。
將標記延伸套用至 XAML 中的控制項
若要在 XAML 程式碼中使用標記延伸,請將包含 GlobalFontSizeExtension 類別的命名空間新增至 ContentPage 標籤中的命名空間清單。 在下列範例中,此命名空間會提供別名 mycode:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:mycode="clr-namespace:MyMauiApp"
x:Class="MyMauiApp.MainPage">
您可以使用標記延伸來設定這一類的 FontSize 屬性。 請注意,依照慣例,標記擴展的名稱會包含後綴Extension。 XAML 會辨識此尾碼,因此在 XAML 程式碼中呼叫該延伸時,已無需包含該尾碼。 在下列範例中,會直接將 GlobalFontSizeExtension 類別參照為 GlobalFontSize:
<Label Text="Hello, World!"
Grid.Row="0"
SemanticProperties.HeadingLevel="Level1"
FontSize="{mycode:GlobalFontSize}"
HorizontalOptions="CenterAndExpand"/>
您可以在整個 XAML 程式碼中,對所有需要指定字型大小的控制項套用相同的標記延伸。 稍後,如果您決定變更字型大小,就只需修改 MainPage 類別中 MyFontSize 變數的定義即可。
StaticExtension 類別
儘管與 GlobalFontSize 標記延伸一樣實用,但不太可能建立這樣的延伸模組。 原因很簡單;.NET MAUI 已提供了更為通用的延伸模組,可讓您參照程式碼中的任何靜態值。 此延伸模組名為 StaticExtension,或簡稱 Static。 下列程式碼顯示此延伸模組類別的基本大綱:
[ContentProperty ("Member")]
public class StaticExtension : IMarkupExtension
{
public string Member {get; set;}
public object ProvideValue (IServiceProvider serviceProvider)
{
...
}
}
注意
自訂標記延伸的用途,是要讓您處理比簡單靜態大小寫更為複雜的情況。 例如,有可能會需要依據裝置的外形規格,以動態方式變更字型大小的情況。
若要在 XAML 程式碼中使用此類別,請提供要在 Member 屬性中參照的靜態變數名稱,ProvideValue 方法即會傳回此變數中的值。 下列範例會說明其使用方法:
<Label Text="Hello, World!"
Grid.Row="0"
SemanticProperties.HeadingLevel="Level1"
FontSize="{x:Static Member=mycode:MainPage.MyFontSize}"
HorizontalOptions="CenterAndExpand"/>
.NET MAUI 會提供一組其他標記延伸類別,您可以將這些類別用於像是資料繫結、參照動態資源和樣式,以及處理資料陣列等案例。