Xamarin.AndroidにBindingとCode-Behindが追加されてたので試してみた

このエントリーをはてなブックマークに追加

Xamarin.Android 9.0 Release Notes - Xamarin

Release notes detailing new features, improvements, and issues fixed in Xamarin.Android 9.0

developer.xamarin.com

Xamarin.Android 9.0 Release Notes - Xamarin
Go to Xamarin.Android 9.0 Release Notes - Xamarin

Xamarin.Androidのリリースノートを見ていたらいつのまにかにBindingとCode-Behindが追加されていたので試してみました。

Not Found

The requested URL could not be found.

github.com

Go to Not Found

スペックなどはドキュメントとしてまとめられているようです。ざっくり言うとXAMLでもなくAndroidのDataBindingでもないBindingとCode-Behindになります。

サンプルコードはGithubに公開しています。

GitHub - MeilCli/XamarinAndroidCodeBehindSample

Contribute to MeilCli/XamarinAndroidCodeBehindSample development by creating an account on GitHub.

github.com

GitHub - MeilCli/XamarinAndroidCodeBehindSample
Go to GitHub - MeilCli/XamarinAndroidCodeBehindSample

機能の有効化

デフォルトでは有効になっていないので有効化する必要があります。

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のクラスをホルダー感覚で参照するだけです。

自動生成されるコードはこんな感じになっています↓

XamarinAndroidCodeBehindSample/XamarinAndroidCodeBehindSample/obj/Debug/MonoAndroid81/generated/Binding.ActivityMain.g.cs at master · MeilCli/XamarinAndroidCodeBehindSample

Contribute to MeilCli/XamarinAndroidCodeBehindSample development by creating an account on GitHub.

github.com

XamarinAndroidCodeBehindSample/XamarinAndroidCodeBehindSample/obj/Debug/MonoAndroid81/generated/Binding.ActivityMain.g.cs at master · MeilCli/XamarinAndroidCodeBehindSample
Go to XamarinAndroidCodeBehindSample/XamarinAndroidCodeBehindSample/obj/Debug/MonoAndroid81/generated/Binding.ActivityMain.g.cs at master · MeilCli/XamarinAndroidCodeBehindSample

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せずともアクセスできます。

XamarinAndroidCodeBehindSample/XamarinAndroidCodeBehindSample/obj/Debug/MonoAndroid81/generated/XamarinAndroidCodeBehindSample.SubActivity.ActivitySub.g.cs at master · MeilCli/XamarinAndroidCodeBehindSample

Contribute to MeilCli/XamarinAndroidCodeBehindSample development by creating an account on GitHub.

github.com

XamarinAndroidCodeBehindSample/XamarinAndroidCodeBehindSample/obj/Debug/MonoAndroid81/generated/XamarinAndroidCodeBehindSample.SubActivity.ActivitySub.g.cs at master · MeilCli/XamarinAndroidCodeBehindSample
Go to XamarinAndroidCodeBehindSample/XamarinAndroidCodeBehindSample/obj/Debug/MonoAndroid81/generated/XamarinAndroidCodeBehindSample.SubActivity.ActivitySub.g.cs at master · MeilCli/XamarinAndroidCodeBehindSample

生成されるコードはこちらなのですが、どうもActivity専用なコード生成されてるように見えますが、Fragmentなどにも使えるのかなどは未確認です(すいません)

自動生成直後は自動生成ファイルが反映されない?

AndroidBoundLayoutでBindingやCode-Behindをしてるせいなのかもしれませんが、自動生成してほしいaxmlを用意し、コードが自動生成されていることを確認してもVisualStudio側のC#エディターで参照が取れませんでした。
プロジェクトのリロードをすると反映されるようです。

一番手っ取り早い方法はソリューションエクスプローラーのツールのぐるぐるアイコンでのリロードですかね。

なお、参照さえ取れればIdの変更などの自動再生成には瞬時に反映されるようです。

この機能使えるのか…?

個人的にはありよりのありです。

AndroidのDataBindingやXamlのようにデータまでのBindingはできないですが、MVVMなアーキテクチャーでReactivePropertyを使っているとFindViewByIdがつらいだけで、Bindingはコードで書いちゃいますので……