Ich habe eine ListView mit einem ArrayAdapter, und jede Zeile im Adapter enthält vier Schaltflächen, die Klickereignisse empfangen und verarbeiten müssen. Normalerweise würde ich bei der Erstellung der Zelle SetOnClickListener
auf jeder Schaltfläche aufrufen, aber Mono bietet stattdessen die Möglichkeit, Ereignishandler für das Ereignis Click
zu setzen. Es sieht jedoch so aus, als gäbe es in Mono etwas Seltsames, weil ich je nachdem, wo ich den Event-Handler eingestellt habe, auf eines der beiden Probleme stoße.
ArrayAdapter GetView Beispiel 1:
%Vor% Hier wird mein Event-Handler nur einmal pro Button gesetzt (gut!), aber der position
-Wert ist meistens falsch. Ich frage mich, ob die Konvertierung von Mono zu Android-Code bewirkt, dass GetItem(position)
immer den gleichen Wert für position
verwendet (der Wert, auf den position
gesetzt wird, wenn die Zelle zum ersten Mal erstellt wird). Dieser Code würde im normalen Android völlig funktionieren.
ArrayAdapter GetView Beispiel 2:
%Vor% Diese Methode bewirkt, dass das click -Ereignis für die korrekte position
ausgelöst wird, setzt jedoch bei jeder Wiederverwendung der Zeile einen neuen Ereignishandler. Dies führt zu Klick-Ereignissen für viele Zeilen gleichzeitig. Eine Problemumgehung für diese Methode scheint darin zu bestehen, Referenzen auf die Event-Handler zu behalten und sie zu entfernen, bevor sie in GetView
erneut gesetzt werden, aber das scheint extrem unelegant zu sein.
Gibt es eine bessere Methode zur Handhabung von Klickereignissen in ListView-Elementen in Monodroid?
Ich weiß, es ist ein alter Thread, aber es hat viele Stimmen und ist immer noch als unbeantwortet markiert.
Es ist nur logisch, dass die von Ihnen beschriebenen Szenarien passieren! Es hat nichts mit Mono zu tun. Es hat mit dem Conversionview zu tun. Dies ist, was die Dokumentation in convertview sagt:
convertView - Die alte Ansicht zur Wiederverwendung, wenn möglich. Hinweis: Sie sollten Überprüfen Sie, ob diese Ansicht nicht null und von einem geeigneten Typ ist verwenden. Wenn es nicht möglich ist, diese Ansicht zu konvertieren, um die Korrekte Daten, diese Methode kann eine neue Ansicht erstellen.
Beispiel 1: In Ihrem ersten Beispiel wird convertView beim ersten Mal null sein und die Ereignisse werden gesetzt. Dann, wenn die Methode GetView das nächste Mal aufgerufen wird, kann Convertview null sein oder nicht. Wenn es nicht null ist, wird es die alte Ansicht mit den noch angehängten Ereignissen verwenden! Das bedeutet also, dass das Ereignis mit dem Positionsparameter noch aus einer vorherigen Ansicht stammt!
Beispiel 2: Dieses Beispiel wird wie erwartet funktionieren, aber es ist nicht sehr effizient, wie Sie erwähnt haben. Es muss die Steuerelemente jedes Mal suchen, wenn die FindViewById -Methode aufgerufen wird.
Lösung: Die Lösung für dieses Leistungsproblem besteht darin, das Viewholder-Muster zu implementieren.
Zuerst erstellen Sie eine Klasse, die Ihre Ansichten enthält:
%Vor%Jetzt können Sie diesen Viewholder in Ihrem Code verwenden
%Vor%Weitere Informationen zu diesem Check-out: Ссылка
Ich hatte auch ähnliche Probleme. Anscheinend werde ich Lösung 2 vermeiden. Außerdem beobachte ich das Problem in Lösung 1 nur bei Android 2.3.
So habe ich das Problem behoben.
Ich behalte einen Verweis auf die ListView
im Adapter, sagen wir _listView
. Dann, in Ihrer GetItem()
-Methode (Verpassen Sie nicht die Variable position
. Ihr Wert ist ein Mysterium), rufen Sie _listView.GetPositionForView((View)sender)
auf, um die richtige Position zu erhalten.
Tags und Links android mono xamarin xamarin.android android-listview