2012-04-17 3 views
7

Nelle ultime due settimane ho lavorato allo sviluppo di un'app cross platform (IOS/Android/WP7) utilizzando il framework MVVMCross. Oggi mi sono imbattuto in un problema che non so davvero come risolvere, quindi spero che tu possa spingermi nella giusta direzione.Passaggio di variabili da ViewModel a un'altra vista (MVVMCross)

Nel IOS ho la costruzione segue per la navigazione verso un'altra pagina (il codice qui sotto si trova in una ViewModel):

KeyValuePair<string,string> kvpAct1 = new KeyValuePair<string, string>("short", ".countertest5"); 

public IMvxCommand BeckhoffActuator1 
{ 
    get 
    {   
     return new MvxRelayCommand<Type>((type) => this.RequestNavigate<Beckhoff.BeckhoffActuatorViewModel>(kvpAct1)); 
    } 
} 

Quando questo IMvxCommand viene licenziato (pulsante premuto) il prossimo View viene caricata, in questo caso il BeckhoffActuatorViewModel. Nel codice del BeckhoffActuatorView uso il KeyValuePair dall'alto:

public class BeckhoffActuatorView : MvxTouchDialogViewController<BeckhoffActuatorViewModel> 
{ 

    ICollection<string> icol; 

    public BeckhoffActuatorView(MvxShowViewModelRequest request) : base(request, UITableViewStyle.Grouped, null, true) 
    { 

     icol = request.ParameterValues.Values; 

    } 

    public override void ViewDidLoad() 
    { 
     //Code 
    } 
} 

Questa costruzione sta lavorando bene in IOS, ma vorrei utilizzare la stessa costruzione nel mio app Android.

Il codice nel ViewModel non è cambiato poiché è l'intera idea di MVVM. Ma il codice della BackhoffActuatorView è diversa per Android:

public class BeckhoffActuatorView : MvxBindingActivityView<BeckhoffSensorViewModel> 
{ 
    public ICollection<string> icol; 

    public BeckhoffActuatorView() 
    { 
     Debug.WriteLine("Standard"); 
    } 

    public BeckhoffActuatorView(MvxShowViewModelRequest request) 
    { 
     Debug.WriteLine("Custom"); 

     icol = request.ParameterValues.Values; 
    } 

    protected override void OnViewModelSet() 
    { 

     SetContentView(Resource.Layout.BeckhoffActuatorView); 

    } 
} 

Il codice di cui sopra non funziona, il MvxBindingActivityView non sembra di implementare qualcosa di simile al ViewController che uso in IOS. Il codice viene solo nel costruttore standard, e quando lo lascio completamente non verrà compilato/eseguito.

Qualcuno sa che posso accedere al keyvaluepair che invio con RequestNavigate? Grazie!

risposta

10

MVVMCross è basato sulla convenzione e funziona sull'idea di passare i messaggi tra ViewModels laddove possibile.

Se si passa a un ViewModel utilizzando:

KeyValuePair<string,string> kvpAct1 = new KeyValuePair<string, string>("short", ".countertest5"); 

public IMvxCommand BeckhoffActuator1 
{ 
    get 
    {   
     return new MvxRelayCommand<Type>((type) => this.RequestNavigate<Beckhoff.BeckhoffActuatorViewModel>(kvpAct1)); 
    } 
} 

allora si dovrebbe essere in grado di raccogliere che fino al BeckhoffActuatorViewModel utilizzando il costruttore:

public class BeckhoffActuatorViewModel : MvxViewModel 
{ 
    public BeckhoffActuatorViewModel(string short) 
    { 
     ShortValue = short; 
    } 

    private string _shortValue; 
    public string ShortValue 
    { 
     get 
     { 
      return _shortValue; 
     } 
     set 
     { 
      _shortValue = value; 
      FirePropertyChanged("ShortValue"); 
     } 
    } 
} 

E le vostre opinioni può quindi accedere ViewModel.ShortValue (per iOS questo può essere fatto dopo base.ViewDidLoad(), per Android dopo OnCreate() e per WP7 dopo OnNavigatedTo)

Per un esempio di questo, date un'occhiata all'esempio TwitterSearch:

Questo ha un HomeViewModel che chiama naviga usando:

private void DoSearch() 
    { 
     RequestNavigate<TwitterViewModel>(new { searchTerm = SearchText }); 
    } 

e un TwitterViewModel che riceve il searchTerm utilizzando il costruttore:

public TwitterViewModel(string searchTerm) 
    { 
     StartSearch(searchTerm); 
    } 

Si noti che in questo messaggio sono consentiti solo gli string, ma è sempre possibile serializzare i propri oggetti utilizzando JSON.Net oppure è possibile estendere il framework: è open source.

Si prega di notare che solo string s, int s, double s e bool s sono ammessi in questo parametro del costruttore di passaggio allo stato attuale - questo è dovuto alle esigenze di serializzazione di XAML URL e per Android Intenti. Se desideri sperimentare la navigazione utilizzando i tuoi oggetti serializzati personalizzati, consulta http://slodge.blogspot.co.uk/2013/01/navigating-between-viewmodels-by-more.html.

Si noti inoltre che se si desidera utilizzare la navigazione oggetto anonimo (RequestNavigate<TwitterViewModel>(new { searchTerm = SearchText });) allora sarà necessario fare in modo che un attributo InternalsVisibleTo è impostato - vedere https://github.com/slodge/MvvmCrossTwitterSearch/blob/master/TwitterSearch.Core/Properties/AssemblyInfo.cs:

[assembly: InternalsVisibleTo("Cirrious.MvvmCross")] 

Ulteriori .. non per i deboli di cuore ... e questo non è un "buon codice mvvm" ... ma se vuoi veramente/aver bisogno di accedere ai dati di MvxShowViewModelRequest all'interno di un'attività Android, puoi estrarlo dall'intento in arrivo - c'è una stringa Extra contenente la richiesta (vedere la deserializzazione in CreateViewModelFromIntent in https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross/Android/Views/MvxAndroidViewsContainer.cs)

+4

Grazie Stuart, utilizzando l'esempio di Twitter sono riuscito a risolvere il mio problema! – David

+0

Buon lavoro: se hai bisogno di un altro esempio di passaggio dei parametri, puoi provare anche gli esempi CustomerManagement e Books :) – Stuart