2012-04-17 17 views
7

Przez ostatnie kilka tygodni pracowałem nad tworzeniem aplikacji wieloplatformowej (IOS/Android/WP7) przy użyciu środowiska MVVMCross. Dziś wpadłem na problem, którego tak naprawdę nie wiem, jak rozwiązać, więc mam nadzieję, że popchniesz mnie we właściwym kierunku.Przekazywanie zmiennych z ViewModel do innego widoku (MVVMCross)

W IOS Mam następującą konstrukcję do nawigowania do innej strony (poniżej kod znajduje się w 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)); 
    } 
} 

Gdy IMvxCommand jest zwolniony (przycisk wciśnięty) następny View jest załadowany, w tym przypadku BeckhoffActuatorViewModel. W kodzie BeckhoffActuatorView używam KeyValuePair z góry:

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 
    } 
} 

Konstrukcja ta działa dobrze w IOS, ale chciałbym używać tej samej konstrukcji w moim Android app.

Kod w ViewModel nie zmienił się, ponieważ to cała idea MVVM. Ale kod BackhoffActuatorView jest różna dla Androida:

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); 

    } 
} 

Powyższy kod nie działa, MvxBindingActivityView nie wydaje się, aby zaimplementować coś podobnego do ViewController używam w IOS. Kod znajduje się tylko w standardowym konstruktorze, a gdy zostawiam go całkowicie, nie będzie on kompilowany/uruchamiany.

Czy ktoś wie, że mogę uzyskać dostęp do kluczowej analizy, którą wysyłam za pośrednictwem usługi RequestNavigate? Dziękuję Ci!

Odpowiedz

10

MVVMCross jest oparty na konwencjach - i działa na zasadzie przesyłania wiadomości między ViewModels, gdy tylko jest to możliwe.

Jeśli przejdź do ViewModel przy użyciu:

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

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

to powinieneś być w stanie podnieść, że nawet w BeckhoffActuatorViewModel za pomocą konstruktora:

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

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

A twoje poglądy mogą następnie przejść ViewModel.ShortValue (dla systemu iOS można to zrobić po base.ViewDidLoad(), dla Androida po OnCreate() i dla WP7 po OnNavigatedTo)

Dla przykładu to, spojrzeć na przykładzie TwitterSearch:

Ma to HomeViewModel który wywołuje nawigować za pomocą:

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

i TwitterViewModel który odbiera SEARCHTERM pomocą konstruktora:

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

Należy pamiętać, że w tej wiadomości są obecnie dozwolone tylko string s, ale zawsze można serializować własne obiekty za pomocą JSON.Net - lub można rozszerzyć framework - to open source.

Należy pamiętać, że tylko string s, int s, double s i bool s są dozwolone w tym parametrze konstruktora przechodzącej obecnie - wynika to z wymagań serializacji dla Xaml adresów URL, a dla Androida zamiarów. Jeśli chcesz poeksperymentować z nawigacją za pomocą własnych niestandardowych serializowanych obiektów, zapoznaj się z artykułem http://slodge.blogspot.co.uk/2013/01/navigating-between-viewmodels-by-more.html.

Należy również pamiętać, że jeśli chcesz użyć anonimowego nawigacja obiektu (RequestNavigate<TwitterViewModel>(new { searchTerm = SearchText });) następnie trzeba się upewnić, że atrybut InternalsVisibleTo jest ustawiony - patrz https://github.com/slodge/MvvmCrossTwitterSearch/blob/master/TwitterSearch.Core/Properties/AssemblyInfo.cs:

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

dalej .. nie dla osób o słabych nerwach ... a to nie jest "dobry kod mvvm" ... ale jeśli naprawdę chcesz/potrzebujesz uzyskać dostęp do danych MvxShowViewModelRequest w ramach aktywności Androida, możesz wyodrębnić je z przychodzących intencji - istnieje ciąg Extras zawierający żądanie (zobacz deserialization w CreateViewModelFromIntent w https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross/Android/Views/MvxAndroidViewsContainer.cs)

+4

Dziękuję Stuart, korzystając z przykładu na Twitterze udało mi się naprawić mój problem! – David

+0

Dobra robota - jeśli potrzebujesz innego przykładu przekazywania parametrów, możesz wypróbować także CustomerManagement i Books :) – Stuart

Powiązane problemy