XAML 標記延伸
大部分的 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 會提供一組其他標記延伸類別,您可以將這些類別用於像是資料繫結、參照動態資源和樣式,以及處理資料陣列等案例。