Xamarin MvvmLight-Binding funktioniert nicht
Inhaltsverzeichnis
Symptom
Sie benutzen in Ihrer Xamarin Android-App oder Ihrer Xamarin iOS-App das Binding mit MVVMLight. Es sollten dabei die Daten aus einem ViewModel an die Controls gebunden werden, z.B. an eine Liste oder an einzelne Labels. Die Bindings setzen Sie dabei in OnCreate (Android) bzw. in ViewDidLoad (iOS):
Android:
public class MeinActivity1 : ActivityBase { private Binding<ArtikelDetails, ArtikelDetails> _meinBinding; protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); _meinBinding = this.SetBinding(() => MeinViewModel.ArtikelDetailsObjekt).WhenSourceChanges(() => { SetArtikelData(); } } }
iOS:
public class MeinViewController1: ControllerBase { private Binding<ArtikelDetails, ArtikelDetails> _meinBinding; public override void ViewDidLoad() { base.ViewDidLoad(); _meinBinding = this.SetBinding(() => MeinViewModel.ArtikelDetailsObjekt).WhenSourceChanges(() => { SetArtikelData(); } } }
Dabei stellen Sie das Problem fest:
Binding funktioniert nicht zuverlässig, die Daten werden nicht immer korrekt in den Controls angezeigt. Manchmal dauert es sehr lange, bis die Daten in die Controls geladen werden. Manchmal werden je-doch auch trotz langer Wartezeit überhaupt keine Daten angezeigt.
Ursache und Lösung
Erstens, Sie sollten das mit MVVMLight erzeugte Binding beim Verlassen der Maske unbedingt wieder abhängen. Sonst bleibt dieses an dem ViewModel hängen und ein erneutes Binding wird bei der Navigation nicht mehr korrekt funktionieren:
if (_meinBinding != null) { _meinBinding.Detach(); _meinBinding = null; }
Zweitens, es ist wichtig, den Lebenszyklus (Lifecycle) einer Activity bzw. eines ViewControllers genauer zu analysieren und Bindings zum jeweils richtigen Zeitpunkt zu behandeln.
Was passiert, wenn Sie ein Binding in OnCreate/OnDestroy (Xamarin Android) bzw. in ViewDid-Load/ViewDidUnLoad (Xamarin iOS) erzeugen und abhängen?
Dies erklären wir am Beispiel des Lifecycles einer Android-Activity:
OnDestroy wird nur dann aufgerufen, wenn MeinActivity1 durch Klick auf den Navigationsbutton <BACK> verlassen wird. Wenn MeinActivity1 lediglich durch Aufruf einer weiteren MeinActivity2 verlassen wird, wird OnDestroy nicht aufgerufen. D.h. das Binding bleibt an Ihrem ViewModel hängen.
Folge: Wenn Sie dann zum MeinActivity1 nochmals neu mit NavigationService.NavigateTo(MeinActivity1Key) navigieren, wird in OnCreate das Binding nochmals erzeugt.
Und dann kommt es ärgerlicherweise zu Kollisionen.
Workaround (nicht optimal, aber funktionierend):
Xamarin Android:
Binding in OnStart erzeugen, und dann in OnStop ablösen (detach).
Xamarin iOS:
Binding in ViewWillAppear erzeugen, und dann in ViewDidDisappear ablösen (detach).
Weitere Informationen
https://www.max-it.de/techcorner/Xamarin_MvvmLight
Links und Quellen
http://developer.xamarin.com/guides/android/application_fundamentals/activity_lifecycle/#Activity_Lifecycle_Methods
http://developer.xamarin.com/guides/android/application_fundamentals/activity_lifecycle/saving_state_walkthrough/
Kontakt
Wenn Sie Fragen oder Anmerkungen zu diesem Artikel haben, melden Sie sich bitte bei uns: mailto:techCorner@max-it.de.
Tags
Xamarin, android, ios, binding, mvvmlight, app