2017-02-08 2 views
4

folgende Ansichtsmodell Gegeben ...Xamarin Forms - eine Steuerkraftwert aktualisieren aus der Bindung

public class NameEntryViewModel 
{ 
    public NameEntryViewModel() 
    { 
     Branding = new Dictionary<string, string>(); 

     Branding.Add("HeaderLabelText", "Welcome to the app"); 
    } 

    public Dictionary<string, string> Branding { get; set; } 
} 

auf die Seite Bound ...

<?xml version="1.0" encoding="utf-8" ?> 
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
      xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
      x:Class="Monaco.Forms.Views.NameEntryPage"> 

     <Label Text="{Binding Branding[HeaderLabelText]}" /> 

</ContentPage> 

Wenn die Seite das Label aufkommt wird Holen Sie sich den Text "Willkommen in der App". Das funktioniert gut und passt in unseren Plan, unsere App anpassen und globalisieren zu können. In diesem Beispiel wird das Branding-Wörterbuch statisch festgelegt, in der realen Welt wird es jedoch durch Daten aus einem Serviceanruf initialisiert.

Wenn der Benutzer jedoch die Sprache auf Spanisch umstellen möchte, müsste jedes gebundene Etikett auf den neuen Wert aktualisiert werden. Es ist einfach, das Branding-Wörterbuch zurückzusetzen und mit spanischen Übersetzungen zu füllen, aber wie können wir die Steuerelemente zwingen, von ihren gebundenen Quellen zu aktualisieren?

Ich versuche, bidirektionale Datenbindung hier zu vermeiden b/c wollen wir nicht den Code-Overhead der Erstellung einer Backing-Eigenschaft für jede Text-Eigenschaft der Steuerelemente. Daher sind wir an ein Werteverzeichnis gebunden.

ANTWORT

nahm ich die Antwort unten, aber ich habe nicht eine traditionelle Eigenschaft Setter verwenden. Stattdessen, wenn ein Benutzer eine andere Sprache wechseln möchte, haben wir jetzt einen zentralisierten Handler, der unser Dictionary neu auffüllt und dann über die Änderung des Dictionary informiert. Wir verwenden MVVMCross, aber Sie können auf Standardformulare übersetzen ...

public MvxCommand CultureCommand 
    { 
     get 
     { 
      return new MvxCommand(async() => 
      { 
       _brandingService.ToggleCurrentCulture(); 
       await ApplyBranding(); // <-- this call repopulates the Branding property 
       RaisePropertyChanged(() => Branding); 
      }); 
     } 
    } 
+2

Sie verwenden können, das Property Ereignis auf der Branding-Eigenschaft erhöhen, und es wird etwas aufzufrischen, die Branding-oder jede Bindung enthält Branding-in seinem Weg bindet. –

Antwort

6

Wie @BillReiss erwähnten Sie die OnPropertyChanged Ereignis erben die NameEntryViewModel von dieser Klasse verwenden müssen:

public class BaseViewModel : INotifyPropertyChanged 
{ 

    protected BaseViewModel() 
    { 

    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void OnPropertyChanged ([CallerMemberName] string propertyName = null) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) 
      handler (this, new PropertyChangedEventArgs (propertyName)); 
    } 
} 

Und erstellen Privateigentum, die Sie Ihnen wie öffentliches Eigentum etwas zuordnen:

Dictionary<string, string> _branding = new Dictionary<string, string>(); 
public Dictionary<string, string> Branding 
{ 
    get 
    { 
     return _branding; 
    } 
    set 
    { 
     _branding = value; 
     OnPropertyChanged(nameof(Branding)); 
    } 
} 

Und damit jedes Mal, wenn Sie die Branding-Eigenschaft wird er die Vi lassen dass sich etwas verändert hat! Manchmal, wenn Sie diese auf einem Back-Thread tun haben Sie Device.BeginInvokeOnMainThread()