android - Monodroid - Handling Click events inside ListAdapter rows -
i have listview arrayadapter set it, , each row in adapter contains 4 buttons need receive , handle click events. in android call setonclicklistener
on each button when create cell, mono gives ability set event handlers click
event instead. looks there's weirdness in mono though, because run 1 of 2 issues depending on set 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, event handler gets set once per button (good!), position
value wrong of time. i'm wondering if conversion mono android code causing getitem(position)
use same value position
every time (the value position
set when cell first created). code 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 cause click event fired correct position
, sets new event handler every time row recycled. causes click events lots of rows @ same time. workaround method seem to keep references event handlers , remove them before setting them again inside getview
, seems extremely inelegant.
is there better method handling click events inside listview items in monodroid?
i know old thread, has lot of votes , still marked unanswered
it logical scenarios described happens! has nothing mono whatsoever. has convertview. documentation says on convertview:
convertview - old view reuse, if possible. note: should check view non-null , of appropriate type before using. if not possible convert view display correct data, method can create new view.
example 1: in first example convertview null first time , events set. next time getview method called convertview may or may not null. if not null use old view events still attached! means event position parameter still previous view!
example 2: example work expected not efficient mentioned. has locate controls every time findviewbyid method called.
solution: solution performance problem implement viewholder pattern.
first create class hold views:
private class myviewholder : java.lang.object { public button movetweet { get; set; } public button sharetweet { get; set; } public button unfavoritetweet { get; set; } public button hidetweet { get; set; } }
now can use viewholder in code
public override view getview (int position, view convertview, viewgroup parent) { myviewholder holder; var view = convertview; if(view != null) holder = view.tag myviewholder; if (holder == null) { holder = new myviewholder (); view = activity.layoutinflater.inflate (resource.layout.optimizeditem, null); holder.movetweet = view.findviewbyid<button> (resource.id. btn_movetweet); holder.sharetweet = view.findviewbyid<button> (resource.id. btn_sharetweet); holder.unfavoritetweet = view.findviewbyid<button> (resource.id. btn_unfavoritetweettweet); holder.hidetweet = view.findviewbyid<button> (resource.id. btn_hidetweet); view.tag = holder; } holder.movetweet.click += (object sender, eventargs e) => movetweet (getitem(position)); holder.unfavoritetweet.click += (object sender, eventargs e) => unfavoritetweet (getitem(position)) holder.hidetweet.click += (object sender, eventargs e) => hidetweet (getitem(position)); holder.favoritetweet.click += (object sender, eventargs e) => sharetweet (getitem(position)); return view; }
for more information on check out: https://blog.xamarin.com/creating-highly-performant-smooth-scrolling-android-listviews/