XAML マークアップ拡張
.NET マルチプラットフォーム アプリ UI (.NET MAUI) XAML マークアップ拡張を使用すると、他のソースから間接的に参照されるオブジェクトまたは値にプロパティを設定できます。 XAML マークアップ拡張は、オブジェクトを共有したり、アプリ全体で使用される定数を参照したりする際、特に重要ですが、最も役に立つのはデータ バインディングです。
通常、XAML を使用して、オブジェクトのプロパティを明示的な値 (文字列、数値、列挙型メンバー、バックグラウンドで値に変換される文字列など) に設定します。 ただし、プロパティが別の場所で定義されている値を参照する必要がある場合や、ランタイムにコードによる処理が少し必要になる場合があります。 このような目的で、XAML マークアップ拡張機能を使用できます。
XAML マークアップ拡張は、IMarkupExtension を実装するクラスのコードによってサポートされているため、名前が付けられます。 独自のカスタム マークアップ拡張を記述することもできます。
多くの場合、XAML マークアップ拡張は、中かっこ { と } で区切られた属性値として表示されるため、XAML ファイルですぐに認識できますが、マークアップ拡張も従来の要素としてマークアップに表示されることがあります。
重要
マークアップ拡張はプロパティを持つことができますが、XML 属性のように設定されません。 マークアップ拡張では、プロパティ設定はコンマで区切られ、中かっこ内に引用符は表示されません。
共有リソース
一部の XAML ページには、プロパティが同じ値に設定された複数のビューが含まれています。 たとえば、これらの Button オブジェクトのプロパティ設定の多くは同じです。
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.SharedResourcesPage"
Title="Shared Resources Page">
<StackLayout>
<Button Text="Do this!"
HorizontalOptions="Center"
VerticalOptions="Center"
BorderWidth="3"
Rotation="-15"
TextColor="Red"
FontSize="24" />
<Button Text="Do that!"
HorizontalOptions="Center"
VerticalOptions="Center"
BorderWidth="3"
Rotation="-15"
TextColor="Red"
FontSize="24" />
<Button Text="Do the other thing!"
HorizontalOptions="Center"
VerticalOptions="Center"
BorderWidth="3"
Rotation="-15"
TextColor="Red"
FontSize="24" />
</StackLayout>
</ContentPage>
これらのプロパティのいずれかを変更する必要がある場合は、変更を 3 回ではなく 1 回だけ行った方がいいでしょう。 これがコードの場合は、定数と静的な読み取り専用オブジェクトを使用すると、このような値の一貫性を保ち、変更しやすくなる可能性があります。
XAML で一般的な解決策の 1 つは、このような値またはオブジェクトをリソース ディクショナリに格納することです。 VisualElement クラスは、ResourceDictionary 型の Resources
という名前のプロパティを定義します。これは、string
型のキーとobject
型の値があるディクショナリです。 このディクショナリにオブジェクトを配置し、マークアップから参照できます。これはすべて XAML で実行できます。
ページでリソース ディクショナリを使用するには、ページの上部で Resources
プロパティ要素タグのペアを含め、これらのタグ内にリソースを追加します。 さまざまな型のオブジェクトと値をリソース ディクショナリに追加できます。 これらの型はインスタンス化できなくてはなりません。 たとえば、抽象クラスにすることはできません。 この型には、パラメーターのない公開用コンストラクターが必要です。 各項目には、x:Key
属性で指定されたディクショナリ キーが必要です。
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.SharedResourcesPage"
Title="Shared Resources Page">
<ContentPage.Resources>
<LayoutOptions x:Key="horzOptions"
Alignment="Center" />
<LayoutOptions x:Key="vertOptions"
Alignment="Center" />
</ContentPage.Resources>
...
</ContentPage>
この例では、2 つのリソースは構造型 LayoutOptions
の値であり、それぞれに一意のキーと 1 つまたは 2 つのプロパティが設定されています。 コードとマークアップでは、LayoutOptions
の静的フィールドを使用する方がはるかに一般的ですが、ここではプロパティを設定する方が便利です。
注
オプションの ResourceDictionary タグは、Resources
タグの子として含めることができます。
その後、リソースは、StaticResource
XAML マークアップ拡張を使用して HorizontalOptions
および VerticalOptions
プロパティを設定することにより、Button オブジェクトで使用できます。
<Button Text="Do this!"
HorizontalOptions="{StaticResource horzOptions}"
VerticalOptions="{StaticResource vertOptions}"
BorderWidth="3"
Rotation="-15"
TextColor="Red"
FontSize="24" />
StaticResource
マークアップ拡張は常に中かっこで区切られ、ディクショナリ キーが含まれます。 名前 StaticResource
が、.NET MAUI でもサポートされている DynamicResource
とこれを区別します。 DynamicResource
は、ランタイムに変更される可能性のある値に関連付けられたディクショナリ キー用です。一方、StaticResource
は、ページ上の要素が構築されると、ディクショナリから要素に 1 回だけアクセスします。 XAML パーサーは StaticResource
マークアップ拡張を検出するたびに、ビジュアル ツリーを検索し、そのキーを含む最初の ResourceDictionary を使用します。
BorderWidth
、Rotation
、FontSize
プロパティの場合は、ディクショナリでダブルを格納する必要があります。 XAML は、x:Double
や x:Int32
のような一般的なデータ型のタグを簡単に定義します。
<ContentPage.Resources>
<LayoutOptions x:Key="horzOptions"
Alignment="Center" />
<LayoutOptions x:Key="vertOptions"
Alignment="Center" />
<x:Double x:Key="borderWidth">3</x:Double>
<x:Double x:Key="rotationAngle">-15</x:Double>
<x:Double x:Key="fontSize">24</x:Double>
</ContentPage.Resources>
これらの追加の 3 つのリソースは、LayoutOptions
値と同じ方法で参照できます。
<Button Text="Do this!"
HorizontalOptions="{StaticResource horzOptions}"
VerticalOptions="{StaticResource vertOptions}"
BorderWidth="{StaticResource borderWidth}"
Rotation="{StaticResource rotationAngle}"
TextColor="Red"
FontSize="{StaticResource fontSize}" />
Color 型のリソースの場合、これらの型の属性を直接割り当てるときに使用するものと同じ文字列表現を使用できます。 .NET MAUI に含まれる型コンバーターは、リソースの作成時に呼び出されます。 また、リソース ディクショナリ内の OnPlatform
クラスを使用して、プラットフォームのさまざまな値を定義することもできます。 次の例では、このクラスを使用してさまざまなテキストの色を設定します。
<OnPlatform x:Key="textColor"
x:TypeArguments="Color">
<On Platform="iOS" Value="Red" />
<On Platform="Android" Value="Aqua" />
</OnPlatform>
OnPlatform
リソースはディクショナリ内のオブジェクトである x:TypeArguments
属性を取得し、ジェネリック クラスである x:Key
属性を取得します。 iOS
およびAndroid
属性は、オブジェクトの初期化時に Color 値に変換されます。
次の例は、6 つの共有値にアクセスする 3 つのボタンを示しています。
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.SharedResourcesPage"
Title="Shared Resources Page">
<ContentPage.Resources>
<LayoutOptions x:Key="horzOptions"
Alignment="Center" />
<LayoutOptions x:Key="vertOptions"
Alignment="Center" />
<x:Double x:Key="borderWidth">3</x:Double>
<x:Double x:Key="rotationAngle">-15</x:Double>
<x:Double x:Key="fontSize">24</x:Double>
<OnPlatform x:Key="textColor"
x:TypeArguments="Color">
<On Platform="iOS" Value="Red" />
<On Platform="Android" Value="Aqua" />
<On Platform="WinUI" Value="#80FF80" />
</OnPlatform>
</ContentPage.Resources>
<StackLayout>
<Button Text="Do this!"
HorizontalOptions="{StaticResource horzOptions}"
VerticalOptions="{StaticResource vertOptions}"
BorderWidth="{StaticResource borderWidth}"
Rotation="{StaticResource rotationAngle}"
TextColor="{StaticResource textColor}"
FontSize="{StaticResource fontSize}" />
<Button Text="Do that!"
HorizontalOptions="{StaticResource horzOptions}"
VerticalOptions="{StaticResource vertOptions}"
BorderWidth="{StaticResource borderWidth}"
Rotation="{StaticResource rotationAngle}"
TextColor="{StaticResource textColor}"
FontSize="{StaticResource fontSize}" />
<Button Text="Do the other thing!"
HorizontalOptions="{StaticResource horzOptions}"
VerticalOptions="{StaticResource vertOptions}"
BorderWidth="{StaticResource borderWidth}"
Rotation="{StaticResource rotationAngle}"
TextColor="{StaticResource textColor}"
FontSize="{StaticResource fontSize}" />
</StackLayout>
</ContentPage>
次のスクリーンショットは、一貫性のあるスタイルを確認しています。
ページの上部に Resources
コレクションを定義するのが一般的ですが、ページ上の他の要素に Resources
コレクションを含めることができます。 たとえば、次の例は、StackLayout に追加されたリソースを示しています。
<StackLayout>
<StackLayout.Resources>
<Color x:Key="textColor">Blue</Color>
</StackLayout.Resources>
...
</StackLayout>
リソース ディクショナリに格納されるオブジェクトの最も一般的な型の 1 つは、プロパティ設定のコレクションを定義する .NET MAUI Style です。 スタイルの詳細については、「XAML を使用したスタイル アプリ」を参照してください。
注
リソース ディクショナリの目的は、オブジェクトを共有することです。 そのため、リソース ディクショナリで Label または Button のようなコントロールを配置しても意味がありません。 同じインスタンスをページで 2 回表示することはできないため、ビジュアル要素を共有できません。
x:Static マークアップ拡張機能
StaticResource
マークアップ拡張に加えて、x:Static
マークアップ拡張もあります。 ただし、StaticResource
はリソース ディクショナリからオブジェクトを返しますが、x:Static
は公開用静的フィールド、公開用静的プロパティ、公開用定数フィールド、または列挙型メンバーにアクセスします。
注
StaticResource
マークアップ拡張は、リソース ディクショナリを定義する XAML 実装でサポートされていますが、x:Static
は x
プレフィックスから明らかなように XAML の組み込み部分です。
次の例では、x:Static
が静的フィールドと列挙型メンバーを明示的に参照する方法を示します。
<Label Text="Hello, XAML!"
VerticalOptions="{x:Static LayoutOptions.Start}"
HorizontalTextAlignment="{x:Static TextAlignment.Center}"
TextColor="{x:Static Colors.Aqua}" />
x:Static
マークアップ拡張の主な用途は、独自のコードから静的フィールドまたはプロパティを参照することです。 たとえば、アプリ全体の複数のページで使用する一部の静的フィールドを含む AppConstants
クラスを次に示します。
namespace XamlSamples
{
static class AppConstants
{
public static readonly Color BackgroundColor = Colors.Aqua;
public static readonly Color ForegroundColor = Colors.Brown;
}
}
XAML ファイルでこのクラスの静的フィールドを参照するには、XML 名前空間宣言を使用して、このファイルが配置されている場所を示す必要があります。 追加の XML 名前空間宣言ごとに、新しいプレフィックスが定義されます。 AppConstants
のようなルート アプリ名前空間のローカル クラスにアクセスするには、プレフィックス local
を使用できます。 名前空間宣言は、CLR (共通言語ランタイム) 名前空間名 (.NET 名前空間名とも呼ばれます) を示す必要があります。これは、C# namespace
定義または using
ディレクティブに表示される名前です。
xmlns:local="clr-namespace:XamlSamples"
.NET 名前空間の XML 名前空間宣言を定義することもできます。 たとえば、これは netstandard
アセンブリ内にある標準 .NET System
名前空間の sys
プレフィックスを次に示します。 これは別のアセンブリなので、アセンブリ名も指定する必要があります (この場合は netstandard
):
xmlns:sys="clr-namespace:System;assembly=netstandard"
注
キーワード clr-namespace
の後にコロン、.NET 名前空間名、セミコロン、キーワード assembly
、等号、アセンブリ名が続きます。
その後、XML 名前空間を宣言すると、静的フィールドを使用できます。
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:XamlSamples"
xmlns:sys="clr-namespace:System;assembly=netstandard"
x:Class="XamlSamples.StaticConstantsPage"
Title="Static Constants Page"
Padding="5,25,5,0">
<StackLayout>
<Label Text="Hello, XAML!"
TextColor="{x:Static local:AppConstants.BackgroundColor}"
BackgroundColor="{x:Static local:AppConstants.ForegroundColor}"
FontAttributes="Bold"
FontSize="30"
HorizontalOptions="Center" />
<BoxView WidthRequest="{x:Static sys:Math.PI}"
HeightRequest="{x:Static sys:Math.E}"
Color="{x:Static local:AppConstants.ForegroundColor}"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
Scale="100" />
</StackLayout>
</ContentPage>
この例では、BoxView ディメンションは Math.PI
と Math.E
に設定されていますが、100 倍にスケーリングできます。
他の XAML マークアップ拡張
いくつかのマークアップ拡張は XAML に組み込まれており、.NET MAUI XAML でサポートされています。 これらの一部はあまり使用されませんが、必要な場合は不可欠です。
- プロパティに既定で
null
以外の値があり、それをnull
に設定する場合は、{x:Null}
マークアップ拡張に設定します。 - プロパティが
Type
型の場合は、マークアップ拡張{x:Type someClass}
を使用してType
オブジェクトに割り当てることができます。 x:Array
マークアップ拡張を使用して、XAML で配列を定義できます。 このマークアップ拡張には、配列内の要素の型を示す、Type
という名前の必須の属性があります。
XAML マークアップ拡張の詳細については、「XAML マークアップ拡張の使用」を参照してください。
次のステップ
.NET MAUI データ バインディングを使用すると、2 つのオブジェクトのプロパティをリンクできるため、一方のオブジェクトを変更すると、もう一方のオブジェクトが変更されます。
.NET MAUI