ふと、LoadFromXaml が public になれば、と思って探して、Xamarin.Forms のコードを見ていったら、
Load Xaml Dynamically At Runtime ? Xamarin Forums
https://forums.xamarin.com/discussion/87727/load-xaml-dynamically-at-runtime
Please make XamlLoader Public ? Xamarin Forums
https://forums.xamarin.com/discussion/87810/please-make-xamlloader-public
需要はあるようなないような。以前、動的にロードしたかったのは Xamarin Live Player 以前の頃だったので、既にあるからまあ特にいらんだろうという感じもするし、XAML をサーバーからダウンロードして切り替えることができたら、少しは違うかもしれないと思ったり。
サンプル
moonmile/XFormsXamlDynamicLoad: Xamarin.FormsでXAMLを動的にロードするサンプル
https://github.com/moonmile/XFormsXamlDynamicLoad
拡張メソッドを定義
ContentPageのLoadFromXamlメソッドが private ならば、自前で作ってしまえ、ってことで自前で作ってしまう。
static class ContentPageExtensions
{
public static TXaml LoadFromXaml<TXaml>(this TXaml view, string xaml)
{
Load(view, xaml);
return view;
}
private static void Load(object view, string xaml)
{
var t = Type.GetType("Xamarin.Forms.Xaml.XamlLoader, Xamarin.Forms.Xaml");
var mi = t.GetRuntimeMethod("Load", new Type[] { typeof(object), typeof(string) });
var obj = mi.Invoke(null, new object[] { view, xaml });
return;
}
}
自前のLoadFromXamlから、本物のXamarin.Forms.Xaml.XamlLoader.Loadを呼び出す。実は、XamlLoaderクラスはinternalなので呼び出せないのだが、Type.GetTypeでロードして、GetRuntimeMethodを使うと呼び出せるんですね。
PrivateObject クラス?(Microsoft.VisualStudio.TestTools.UnitTesting)
https://msdn.microsoft.com/ja-jp/library/microsoft.visualstudio.testtools.unittesting.privateobject.aspx
と同じことをやります。
メインページから遷移するときに、自前で XAML をロードさせます。コード内に書いちゃうとリソースで XAML にしたほうが楽だろう(実際そうだし)と思うのですが、似たような感じでネット上から XAML をダウンロードすることも可能ということで。
private void Button_Clicked(object sender, EventArgs e)
{
var xaml = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
<ContentPage xmlns=""http://xamarin.com/schemas/2014/forms""
xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml"">
<StackLayout>
<Label Text=""Hello Sub Page"" />
<Button Text=""click me!"" Clicked=""Button_Clicked"" />
<Label Text=""{Binding Count, StringFormat='{0} clicked'}"" />
</StackLayout>
</ContentPage>
";
/// XAML を動的にロードする
this.Navigation.PushAsync(new SubPage().LoadFromXaml(xaml));
}
SubPage クラスのほうは MVVM も効くので、ViewModel クラスだけで取り廻して XAML のほうは動的に切り替えることもできるかな、と。
public class SubPageViewModel : ObservableObject
{
private int count = 0;
public int Count
{
get { return count; }
set { SetProperty(ref count, value, nameof(Count)); }
}
}
public class SubPage : ContentPage
{
public SubPage()
{
vm = new SubPageViewModel();
this.BindingContext = vm;
}
SubPageViewModel vm;
private void Button_Clicked(object sender, EventArgs e)
{
vm.Count++;
}
}

