2012-04-17 28 views
7

Durante las últimas semanas he estado trabajando en el desarrollo de una aplicación multiplataforma (IOS/Android/WP7) utilizando el framework MVVMCross. Hoy me encontré con un problema que realmente no sé cómo resolver, así que espero que puedas empujarme en la dirección correcta.Pasando variables de ViewModel a otra Vista (MVVMCross)

En el IOS he la construcción siguiente para navegar a otra página (debajo del código se encuentra en un modelo de vista):

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

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

Cuando se activa esta IMvxCommand (botón pulsado) la siguiente vista se carga, en este caso, BeckhoffActuatorViewModel. En el código de la BeckhoffActuatorView utilizo el KeyValuePair desde arriba:

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

Esta construcción está trabajando muy bien en iOS, pero me gustaría utilizar la misma construcción en mi aplicación Android.

El código en ViewModel no ha cambiado ya que esa es la idea general de MVVM. Sin embargo, el código de la BackhoffActuatorView es diferente para 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); 

    } 
} 

El código anterior no está funcionando, el MvxBindingActivityView no parece poner en práctica algo similar a la ViewController que utilizo en IOS. El código solo viene en el constructor estándar, y cuando lo dejo completamente no se compilará/ejecutará.

¿Alguien sabe que puedo acceder al par de valores clave que envío con RequestNavigate? ¡Gracias!

Respuesta

10

MVVMCross está basado en la convención, y funciona con la idea de pasar mensajes entre ViewModels siempre que sea posible.

Si se desplaza a un modelo de vista usando:

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

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

entonces usted debería ser capaz de recoger hasta que en el BeckhoffActuatorViewModel utilizando el constructor:

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

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

Y sus puntos de vista se puede acceder ViewModel.ShortValue (para iOS esto se puede hacer después de base.ViewDidLoad(), para Android después de OnCreate() y para WP7 después de OnNavigatedTo)

Para un ejemplo de esto, echar un vistazo al ejemplo TwitterSearch:

Esto tiene un HomeViewModel que llama a navegar usando:

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

y una TwitterViewModel que recibe el searchTerm utilizando el constructor:

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

Tenga en cuenta que solo se permiten string s en este mensaje que pasa actualmente, pero siempre puede serializar sus propios objetos usando JSON.Net o puede ampliar el marco, es de código abierto.

Tenga en cuenta que sólo string s, s, intdouble s y s bool están permitidos en este parámetro constructor que pasa en la actualidad - esto es debido a los requisitos de serialización para Xaml URLs y para Propósitos Android. Si desea experimentar con la navegación utilizando sus propios objetos serializados personalizados, consulte http://slodge.blogspot.co.uk/2013/01/navigating-between-viewmodels-by-more.html.

Además, tenga en cuenta que si desea utilizar la navegación objeto anónimo (RequestNavigate<TwitterViewModel>(new { searchTerm = SearchText });), entonces tendrá que asegurarse de que un atributo se establece InternalsVisibleTo - ver https://github.com/slodge/MvvmCrossTwitterSearch/blob/master/TwitterSearch.Core/Properties/AssemblyInfo.cs:

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

más .. .no para los débiles de corazón ... y este no es un "buen código de mvvm" ... pero si realmente quiere/necesita acceder a los datos de MvxShowViewModelRequest dentro de una actividad de Android, puede extraerlos del Intento entrante - hay una cadena Extras que contiene la solicitud (ver la deserialización en CreateViewModelFromIntent en https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross/Android/Views/MvxAndroidViewsContainer.cs)

+4

Gracias Stuart, usando el ejemplo de Twitter logré solucionar mi problema. – David

+0

Buen trabajo: si necesita otro ejemplo de aprobación de parámetros, puede probar las muestras CustomerManagement y Books también :) – Stuart

Cuestiones relacionadas