Xamarin.Androidのリリースノートを見ていたらいつのまにかにBindingとCode-Behindが追加されていたので試してみました。
xamarin-android/LayoutCodeBehind.md at master · xamarin/xamarin-android · GitHub
スペックなどはドキュメントとしてまとめられているようです。ざっくり言うとXAMLでもなくAndroidのDataBindingでもないBindingとCode-Behindになります。
サンプルコードはGithubに公開しています。
機能の有効化
デフォルトでは有効になっていないので有効化する必要があります。
csprojを編集することで有効化できます。
<PropertyGroup> <AndroidGenerateLayoutBindings>true</AndroidGenerateLayoutBindings> </PropertyGroup>
しかし、私はcsprojの編集がめんどくさいので、axml単位での有効化をしました。
axml単位で有効化するにはaxmlのプロパティを開き、ビルドアクションをAndroidBoundLayout
にします。
Binding
Bindingといっても今のところはFindViewByIdを省けるぐらいの機能しかないようです(?)
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" xmlns:xamarin="http://schemas.xamarin.com/android/xamarin/tools" android:layout_width="match_parent" android:layout_height="match_parent"> // 略
axmlのルート要素にxmlns:xamarin="http://schemas.xamarin.com/android/xamarin/tools"
を記述するだけでBindingのクラスが自動生成されます。
namespace XamarinAndroidCodeBehindSample { [Activity(Label = "@string/app_name", Theme = "@style/AppTheme.NoActionBar", MainLauncher = true)] public class MainActivity : AppCompatActivity { public MainActivity() { } public MainActivity(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer) { } protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); SetContentView(Resource.Layout.ActivityMain); var binding = new Binding.ActivityMain(this); SetSupportActionBar(binding.Toolbar); binding.FloatingActionButton.Click += fabClicked; } private void fabClicked(object sender, EventArgs eventArgs) { StartActivity(new Intent(this, typeof(SubActivity))); } } }
あとは自動生成されたBindingのクラスをホルダー感覚で参照するだけです。
自動生成されるコードはこんな感じになっています↓
Code-Behind
Code-BehindはBindingを利用した機能で、Bindingのクラスを用意しなくてよくするような感じの機能です。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xamarin="http://schemas.xamarin.com/android/xamarin/tools" xamarin:classes="XamarinAndroidCodeBehindSample.SubActivity" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/Message" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout>
axmlでCode-Behind対象のクラスをxamarin:classes="XamarinAndroidCodeBehindSample.SubActivity"
のように名前空間ごと指定してあげるとpartialクラスが自動生成されます。
namespace XamarinAndroidCodeBehindSample { [Activity] public partial class SubActivity : AppCompatActivity { public SubActivity() { } public SubActivity(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer) { } protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); SetContentView(Resource.Layout.ActivitySub); Message.Text = "Hello World"; } } }
partialクラスが自動生成されるので、ユーザーが作成するActivityのコードもpartialにしてあげることで、ViewをFindViewByIdやBindingせずともアクセスできます。
生成されるコードはこちらなのですが、どうもActivity専用なコード生成されてるように見えますが、Fragmentなどにも使えるのかなどは未確認です(すいません)
自動生成直後は自動生成ファイルが反映されない?
AndroidBoundLayout
でBindingやCode-Behindをしてるせいなのかもしれませんが、自動生成してほしいaxmlを用意し、コードが自動生成されていることを確認してもVisualStudio側のC#エディターで参照が取れませんでした。
プロジェクトのリロードをすると反映されるようです。
一番手っ取り早い方法はソリューションエクスプローラーのツールのぐるぐるアイコンでのリロードですかね。
なお、参照さえ取れればIdの変更などの自動再生成には瞬時に反映されるようです。
この機能使えるのか…?
個人的にはありよりのありです。
AndroidのDataBindingやXamlのようにデータまでのBindingはできないですが、MVVMなアーキテクチャーでReactivePropertyを使っているとFindViewByIdがつらいだけで、Bindingはコードで書いちゃいますので……