ふと、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 ならば、自前で作ってしまえ、ってことで自前で作ってしまう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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 をダウンロードすることも可能ということで。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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 のほうは動的に切り替えることもできるかな、と。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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++; } } |