ふと、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++; } }