Utilizzo di MvvmCross su un progetto mobile multipiattaforma e ho 2 visualizzazioni diverse in un progetto MonoTouch che utilizzano lo stesso modello di visualizzazione condiviso e non sono sicuro di come strutturare il mio codice per navigare viste differenti usando lo stesso viewmodel in MvvmCross.MvvmCross - Condivisione di modelli di visualizzazione per più viste
risposta
La convenzione di default utilizzata dalla piattaforma MvvmCross consiste nel registrare automaticamente tutte le viste mediante la riflessione.
Questo viene fatto in classe di installazione di base - in https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross/Platform/MvxBaseSetup.cs:
protected virtual void InitializeViews()
{
var container = this.GetService<IMvxViewsContainer>();
foreach (var pair in GetViewModelViewLookup())
{
Add(container, pair.Key, pair.Value);
}
}
dove GetViewModelViewLookup
restituisce un dizionario di tipo ViewModel al tipo di vista:
protected virtual IDictionary<Type, Type> GetViewModelViewLookup(Assembly assembly, Type expectedInterfaceType)
{
var views = from type in assembly.GetTypes()
let viewModelType = GetViewModelTypeMappingIfPresent(type, expectedInterfaceType)
where viewModelType != null
select new { type, viewModelType };
return views.ToDictionary(x => x.viewModelType, x => x.type);
}
In universale iPad/iPhone apps che fai ogni tanto vuoi includere più viste per ciascun modello di vista - utilizzando una vista nell'iPad e una vista nell'iPhone.
Per fare questo, ci sono ora (letteralmente solo ora!) Alcuni attributi disponibili per contrassegnare le vostre opinioni come "non convenzionale" - questi sono:
MvxUnconventionalViewAttribute
- uso questo per segnala che la tua vista dovrebbe mai mai inclusa per convenzione
- in https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross/Views/Attributes/MvxUnconventionalViewAttribute.cs
MvxConditionalConventionalViewAttribute
- un attributo abstract - ignorare questo per fornire il proprio logica personalizzata per l'inclusione/esclusione
- in https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross/Views/Attributes/MvxConditionalConventionalViewAttribute.cs
MvxFormFactorSpecificViewAttribute
- iOS/Touch solo
- un attributo che includerà la vista se e solo se il fattore di forma iPhone rilevato corrisponde al dispositivo corrente
- in https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross/Touch/Views/Attributes/MvxFormFactorSpecificViewAttribute.cs
L'ultimo di questi è probabilmente quello che volete in questo caso - si potrebbe implementare semplice commutazione iPhone/iPad per una MainViewModel utilizzando due viste dichiarato come:
[MvxFormFactorSpecificView(MvxTouchFormFactor.Phone)]
public class MyIPhoneView : BaseView<MainViewModel>
{
// iphone specific view ...
}
[MvxFormFactorSpecificView(MvxTouchFormFactor.Pad)]
public class MyIPadView : BaseView<MainViewModel>
{
// ipad specific view ...
}
In alternativa, se si desidera una configurazione molto personalizzata, è possibile ignorare tutti i comportamenti basati sulle convenzioni - è possibile implementare il proprio override di GetViewModelViewLookup
- ad es.:
protected override IDictionary<Type, Type> GetViewModelViewLookup(Assembly assembly, Type expectedInterfaceType)
{
if (IsIPad)
{
return new Dictionary<Type, Type>()
{
{ typeof(HomeViewModel), typeof(IPadHomeView) },
{ typeof(DetailViewModel), typeof(IPadDetailView) },
{ typeof(AboutViewModel), typeof(SharedAboutView) },
};
}
else
{
return new Dictionary<Type, Type>()
{
{ typeof(HomeViewModel), typeof(IPhoneHomeView) },
{ typeof(DetailViewModel), typeof(IPhoneDetailView) },
{ typeof(AboutViewModel), typeof(SharedAboutView) },
};
}
}
Nota che alla fine si può decidere che è necessario ViewModels aggiuntivi e vista per l'applicazione iPad - iPad ha, dopo tutto, uno schermo molto più grande - in questo caso si può aggiungili manualmente. In definitiva, quando la tua app raggiunge milioni di utenti, potresti persino decidere di escludere completamente il codice tablet dal codice del telefono, ma generalmente puoi aspettare fino a quando non raggiungi quei pochi milioni di ...
Un altro modo per fare è di andare avanti e creare 2 ViewModels, ma hanno entrambi sottoclasse un abstract ViewModel, come segue:
FirstViewViewModel : BaseViewModel
SecondViewViewModel : BaseViewModel
con la corrispondente viste con nome:
FirstView.xaml
SecondView.xaml
in questo modo, si è in grado di collocare alcuni comportamenti condivisi in BaseViewMod el, mentre le 2 sottoclassi sono davvero lì solo per soddisfare le convenzioni di visualizzazione di MvvmCross.
Recentemente ho iniziato con MvvmCross e sto usando v4.2.1. Sembra che alcuni nomi siano cambiati. Sto usando un ViewModel con le viste separate di iPhone e iPad con il seguente:
[MvxFormFactorSpecific(MvxIosFormFactor.Phone)]
public class MyIPhoneView : BaseView<MainViewModel>
{
// iphone specific view ...
}
[MvxFormFactorSpecific(MvxIosFormFactor.TallPhone)]
public class MyTallIPhoneView : BaseView<MainViewModel>
{
// tall iphone specific view ...
}
[MvxFormFactorSpecific(MvxIosFormFactor.Pad)]
public class MyIPadView : BaseView<MainViewModel>
{
// ipad specific view ...
}
C'è un modo semplice per Android? Ho un ViewModel generico e voglio diverse viste basate su axml che condividono lo stesso ViewModel. – j7nn7k
Mi dispiace, non importa :) Se qualcun altro lo sta cercando: Override 'OnViewModelSet()' – j7nn7k