I have a ListView with an ArrayAdapter set to it, and each row in the adapter contains four buttons that need to receive and handle click events. Normally in Android I would call SetOnClickListener
on each button when I create the cell, but Mono gives the ability to set event handlers for the Click
event instead. It looks like there's some weirdness to this in Mono though, because I run into one of two issues depending on where I set the event handler.
ArrayAdapter GetView Example 1:
View tweetCell = convertView;
if (tweetCell == null) {
tweetCell = ((LayoutInflater)Context.GetSystemService (Context.LayoutInflaterService)).Inflate (Resource.Layout.TweetCell, null);
tweetCell.FindViewById (Resource.Id.btn_moveTweet).Click += (object sender, EventArgs e) => MoveTweet (GetItem(position));
tweetCell.FindViewById (Resource.Id.btn_unfavoriteTweet).Click += (object sender, EventArgs e) => UnfavoriteTweet (GetItem(position));
tweetCell.FindViewById (Resource.Id.btn_hideTweet).Click += (object sender, EventArgs e) => HideTweet (GetItem(position));
tweetCell.FindViewById (Resource.Id.btn_shareTweet).Click += (object sender, EventArgs e) => ShareTweet (GetItem(position));
}
Here, my event handler only gets set once per button (good!), but the position
value is wrong most of the time. I'm wondering if the conversion from Mono to Android code is causing GetItem(position)
to use the same value for position
every time (the value that position
is set to when the cell is first created). This code would work totally fine in normal Android.
ArrayAdapter GetView Example 2:
View tweetCell = convertView;
if (tweetCell == null) {
tweetCell = ((LayoutInflater)Context.GetSystemService (Context.LayoutInflaterService)).Inflate (Resource.Layout.TweetCell, null);
}
tweetCell.FindViewById (Resource.Id.btn_moveTweet).Click += (object sender, EventArgs e) => MoveTweet (GetItem(position));
tweetCell.FindViewById (Resource.Id.btn_unfavoriteTweet).Click += (object sender, EventArgs e) => UnfavoriteTweet (GetItem(position));
tweetCell.FindViewById (Resource.Id.btn_hideTweet).Click += (object sender, EventArgs e) => HideTweet (GetItem(position));
tweetCell.FindViewById (Resource.Id.btn_shareTweet).Click += (object sender, EventArgs e) => ShareTweet (GetItem(position));
This method does cause the click event to be fired for the correct position
, but it sets a new event handler every time the row is recycled. This causes click events for lots of rows at the same time. A workaround for this method would seem to be to keep references to the event handlers and remove them before setting them again inside GetView
, but this seems extremely inelegant.
Is there a better method for handling click events inside ListView items in Monodroid?