Corrado's Blog 2.0

Online thoughts of a technology funatic

Declarative event handlers in Xamarin Android

In Android applications the UI components are totally isolated from associated activity so to ‘glue’ them you need to follow a ‘javascript like’ approach: find the element fist  and then interact with it. Let’s say you have a .axml file containing a button with id MyButton

 <Button
        android:id="@+id/MyButton"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/Hello" />

in the associated activity, to subscribe its Click event you have to write this code:

public class MainActivity : Activity
 {
  int count = 1;

  protected override void OnCreate(Bundle bundle)
  {
   base.OnCreate(bundle);

   SetContentView(Resource.Layout.Main);
   Button button = FindViewById<Button>(Resource.Id.MyButton);
   button.Click += button_Click;
  }

  void button_Click(object sender, EventArgs e)
  {
   (sender as Button).Text = string.Format("{0} clicks!", count++);
  }
 }

If you, like me, come from XAML and love the declarative approach I’ve got a good new for you, there’s an alternative, just follow this steps:

1-Add a reference to Mono.Android.Export library

2-Declare you handler in .axml file this way:

<Button
        android:id="@+id/MyButton"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/Hello"
    android:onClick="myHandler"/>

3-Refactor the code in associated activity this way:

public class MainActivity : Activity
 {
  int count = 1;

  protected override void OnCreate(Bundle bundle)
  {
   base.OnCreate(bundle);

   SetContentView(Resource.Layout.Main);
  }

  [Java.Interop.Export("myHandler")]
  public void button_Click(View v)
  {
   (v as Button).Text = string.Format("{0} clicks!", count++);
  }
 }

And you’re done!

As you see the trick is to export the function, using the Java.Interop.Export attribute that also allows you to use a export the method with a different name, leave it empty if you don’t need to differentiate.

Lot simpler, and cleaner… IMHO Smile