Xamarin MvvmLight-Binding funktioniert nicht: Unterschied zwischen den Versionen

 
Zeile 1: Zeile 1:
 
==='''Symptom'''===
 
==='''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<br />
+
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):<br /><br />
an die Controls gebunden werden, z.B. an eine Liste oder an einzelne Labels. Die Bindings setzen Sie dabei in OnCreate (Android)<br />
 
bzw. in ViewDidLoad (iOS):<br /><br />
 
 
Android:<br />
 
Android:<br />
 
<pre> public class MeinActivity1 : ActivityBase
 
<pre> public class MeinActivity1 : ActivityBase
Zeile 38: Zeile 36:
 
}
 
}
 
</pre><br />
 
</pre><br />
Dabei stellen Sie das Problem fest:<br /><br />
+
Dabei stellen Sie das Problem fest:<br />  
Binding funktioniert nicht zuverlässig, die Daten werden nicht immer korrekt in den Controls angezeigt. Manchmal dauert es sehr lange,<br />
+
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.  
bis die Daten in die Controls geladen werden. Manchmal werden je-doch auch trotz langer Wartezeit überhaupt keine Daten angezeigt.  
+
 
 
==='''Ursache und Lösung'''===
 
==='''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<br />
+
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:
und ein erneutes Binding wird bei der Navigation nicht mehr korrekt funktionieren:
 
 
<pre> if (_meinBinding != null)
 
<pre> if (_meinBinding != null)
 
             {
 
             {
Zeile 50: Zeile 47:
 
             }
 
             }
 
</pre>
 
</pre>
Zweitens, es ist wichtig, den Lebenszyklus (Lifecycle) einer Activity bzw. eines ViewControllers genauer zu analysieren<br />
+
Zweitens, es ist wichtig, den Lebenszyklus (Lifecycle) einer Activity bzw. eines ViewControllers genauer zu analysieren und Bindings zum jeweils richtigen Zeitpunkt zu behandeln.<br /><br />
und Bindings zum jeweils richtigen Zeitpunkt zu behandeln.<br /><br />
 
 
Was passiert, wenn Sie ein Binding in OnCreate/OnDestroy (Xamarin Android) bzw. in ViewDid-Load/ViewDidUnLoad (Xamarin iOS) erzeugen und abhängen? <br /><br />
 
Was passiert, wenn Sie ein Binding in OnCreate/OnDestroy (Xamarin Android) bzw. in ViewDid-Load/ViewDidUnLoad (Xamarin iOS) erzeugen und abhängen? <br /><br />
 
Dies erklären wir am Beispiel des Lifecycles einer Android-Activity:
 
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.<br />
+
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.<br />
Wenn MeinActivity1 lediglich durch Aufruf einer weiteren MeinActivity2 verlassen wird, wird OnDestroy nicht aufgerufen.<br />
 
D.h. das Binding bleibt an Ihrem ViewModel hängen.<br />
 
 
<br />
 
<br />
Folge: Wenn Sie dann zum MeinActivity1 nochmals neu mit  NavigationService.NavigateTo(MeinActivity1Key)  navigieren,<br />
+
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.<br /><br />
wird in OnCreate das Binding nochmals erzeugt.<br />
 
Und dann kommt es ärgerlicherweise zu Kollisionen.<br /><br />
 
 
Workaround (nicht optimal, aber funktionierend): <br /><br />
 
Workaround (nicht optimal, aber funktionierend): <br /><br />
 
Xamarin Android:
 
Xamarin Android:
Zeile 80: Zeile 72:
 
[http://mailto:techcorner@max-it.de techcorner@max-it.de].<br />
 
[http://mailto:techcorner@max-it.de techcorner@max-it.de].<br />
  
Über m.a.x. Informationstechnologie AG: <br />
+
'''Über m.a.x. Informationstechnologie AG:''' <br />
Als etabliertes Münchner Systemhaus zeichnen wir uns seit 1989 als verlässlicher IT-Partner mittelständischer und<br />
+
Als etabliertes Münchner Systemhaus zeichnen wir uns seit 1989 als verlässlicher IT-Partner mittelständischer und großer Unternehmen aus. Unser Portfolio reicht von IT- Services über individuelle Softwareentwicklung bis hin zur ERP-Beratung.
großer Unternehmen aus. Unser Portfolio reicht von IT- Services über individuelle Softwareentwicklung bis hin zur ERP-Beratung.<br />
+
 
<br />
 
 
==='''Tags'''===
 
==='''Tags'''===
 
Xamarin, android, ios, binding, mvvmlight, app
 
Xamarin, android, ios, binding, mvvmlight, app
  
 
[[Kategorie:Softwareentwicklung]]
 
[[Kategorie:Softwareentwicklung]]

Aktuelle Version vom 14. Mai 2020, 13:44 Uhr

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

Mehr Informationen zu unseren Softwarelösungen und Services finden Sie auf
www.max-it.de/Softwarelösungen

Links und Quellen

www.developer.xamarin.com/guides/android/application_fundamentals/activity_lifecycle/#Activity_Lifecycle_Methods
www.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:
techcorner@max-it.de.

Über m.a.x. Informationstechnologie AG:
Als etabliertes Münchner Systemhaus zeichnen wir uns seit 1989 als verlässlicher IT-Partner mittelständischer und großer Unternehmen aus. Unser Portfolio reicht von IT- Services über individuelle Softwareentwicklung bis hin zur ERP-Beratung.

Tags

Xamarin, android, ios, binding, mvvmlight, app