Xamarin.Forms での実行時の XAML の読み込み
Xamarin.Forms.Xaml
名前空間には、実行時に XAML の読み込みと解析に使用できる 2 つの LoadFromXaml
拡張メソッドが含まれています。
背景
Xamarin.Forms XAML クラスが構築されると、LoadFromXaml
メソッドが間接的に呼び出されます。 これは、XAML クラスのコードビハインド ファイルがコンストラクターから InitializeComponent
メソッドを呼び出すために発生します。
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
}
Visual Studio は、XAML ファイルを含むプロジェクトをビルドすると、XAML ファイルを解析して、たとえば MainPage.xaml.g.cs など、InitializeComponent
メソッドの定義を含む C# コード ファイルを生成します。
private void InitializeComponent()
{
global::Xamarin.Forms.Xaml.Extensions.LoadFromXaml(this, typeof(MainPage));
...
}
InitializeComponent
メソッドは LoadFromXaml
メソッドを呼び出して、.NET Standard ライブラリから XAML ファイル (またはそのコンパイル済みバイナリ) を抽出します。 抽出後は XAML ファイルで定義されているすべてのオブジェクトを初期化し、それらを親子関係で接続し、コードで定義されたイベント ハンドラーを XAML ファイルで設定されたイベントにアタッチし、結果として得られるオブジェクトのツリーをページのコンテンツとして設定します。
実行時の XAML の読み込み
LoadFromXaml
メソッドは public
なので、Xamarin.Forms アプリケーションから呼び出して読み込み、実行時に XAML を解析できます。 これにより、アプリケーションが Web サービスから XAML をダウンロードし、XAML から必要なビューを作成してアプリケーションに表示するなどのシナリオが可能になります。
警告
ランタイム時の XAML の読み込みはパフォーマンス コストが大きく、通常は避ける必要があります。
次のコードは、簡単な使用例を示しています。
using Xamarin.Forms.Xaml;
...
string navigationButtonXAML = "<Button Text=\"Navigate\" />";
Button navigationButton = new Button().LoadFromXaml(navigationButtonXAML);
...
_stackLayout.Children.Add(navigationButton);
この例では、Button
インスタンスが作成され、その Text
プロパティ値が、string
で定義されている XAML から設定されます。 その後、Button
が、ページの XAML で定義されている StackLayout
に追加されます。
注
LoadFromXaml
拡張メソッドを使用すると、ジェネリック型引数を指定できます。 ただし、操作対象のインスタンスの型から推論されるため、型引数を指定する必要はほとんどありません。
この LoadFromXaml
メソッドを使用すると、任意の XAML を拡張できます。次の例では、ContentPage
を拡張してから、それに移動します。
using Xamarin.Forms.Xaml;
...
// See the sample for the full XAML string
string pageXAML = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<ContentPage xmlns=\"http://xamarin.com/schemas/2014/forms\"\nxmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\nx:Class=\"LoadRuntimeXAML.CatalogItemsPage\"\nTitle=\"Catalog Items\">\n</ContentPage>";
ContentPage page = new ContentPage().LoadFromXaml(pageXAML);
await Navigation.PushAsync(page);
要素へのアクセス
LoadFromXaml
メソッドを使用して実行時に XAML を読み込む場合、(x:Name
を使用して) ランタイム オブジェクト名を指定した XAML 要素への厳密に型指定されたアクセスは許可されません。 ただし、これらの XAML 要素は FindByName
メソッドを使用して取得し、必要に応じてアクセスできます。
// See the sample for the full XAML string
string pageXAML = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<ContentPage xmlns=\"http://xamarin.com/schemas/2014/forms\"\nxmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\nx:Class=\"LoadRuntimeXAML.CatalogItemsPage\"\nTitle=\"Catalog Items\">\n<StackLayout>\n<Label x:Name=\"monkeyName\"\n />\n</StackLayout>\n</ContentPage>";
ContentPage page = new ContentPage().LoadFromXaml(pageXAML);
Label monkeyLabel = page.FindByName<Label>("monkeyName");
monkeyLabel.Text = "Seated Monkey";
...
この例では、ContentPage
の XAML が拡張されています。 この XAML には、monkeyName
という名前の Label
が含まれています。これは、Text
プロパティが設定される前に FindByName
メソッドを使用して取得されます。