2013-01-02 15 views
31

È corretto memorizzare tutti i miei ViewModels in SimpleIoc? Ad esempio, ho tre pagine MainPage, Foto, Directory (quindi tre ViewModels -> MainVM, PhotosVM, DirectoriesVM). Devo impostare DataContext in ogni pagina per visualizzare la proprietà del modello in ViewModelLocator o nidificare ViewModels come proprietà in MainVM e associare ciascuna pagina DataContext a Main.PhotosVMProperty, Main.DirectoriesVMProperty e così via? Qualcuno potrebbe spiegarmi l'idea e lo scopo di IoC?ViewModels in ViewModelLocator MVVM Light

+1

Spero che questo ti aiuti: http://stackoverflow.com/questions/13795596/best-tutorial-to-learn-mvvmlight-simpleioc-use – User1551892

+0

puoi fornire un codice relativo al tuo secondo approccio? Come definisci PhotosVMProperty in MainViewModel ... la tua domanda è molto interessante ... – User1551892

risposta

110

In primo luogo, permette di guardare a ciò che fa ViewModelLocator e perché lo usiamo:

ViewModelLocator è dichiarato come un oggetto sulla nostra pagina App.xaml ed è un Singleton applicazione. Ne avremo uno e solo uno sarà disponibile per l'applicazione quando viene eseguita.

ViewModelLocator è la fonte di tutti i nostri ViewModels in MVVM Light. Per ogni ViewModel avremo una proprietà su ViewModelLocator che ci consentirà di ottenere un ViewModel per una vista. Questo codice è simile al seguente:

public class ViewModelLocator 
{ 
    public MainPageViewModel MainPage 
    { 
     get { return new MainPageViewModel(); } 
    } 
} 

Questo è un pezzo della mia App.xaml:

<Application.Resources> 
    <vm:ViewModelLocator 
     x:Key="ViewModelLocator" /> 
</Application.Resources> 

Questo è un pezzo da View.xaml

DataContext="{Binding MainPage, Source={StaticResource ViewModelLocator}}" 

Fin qui tutto bene. Per rispondere alla tua prima domanda, devi utilizzare Ioc in MVVM Light? No. Non è necessario in quanto il tuo viewmodel verrà dato alla tua vista completamente costruita e istanziata da ViewModelLocator.

Ora, sulla tua seconda domanda: qual è lo scopo di IoC?

IOC è stato progettato per consentire di effettuare le seguenti operazioni:

Con MVVM luce si fa quanto sopra in questo modo:

public class ViewModelLocator 
{ 
    public ViewModelLocator() 
    { 
     ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); 

     if (ViewModelBase.IsInDesignModeStatic) 
     { 
      SimpleIoc.Default.Register<IDataService, Design.DesignDataService>(); 
     } 
     else 
     { 
      SimpleIoc.Default.Register<IDataService, DataService>();   
     } 

     SimpleIoc.Default.Register<MainViewModel>(); 
    } 

    public MainViewModel Main 
    { 
     get { return SimpleIoc.Default.GetInstance<MainViewModel>(); } 
    } 
} 

public class MainViewModel 
{ 
    public ObservableCollection<Foo> Foos { get; set; } 

    public MainViewModel(IDataService dataService) 
    { 
     _dataService=dataService; 
     Foos=_dataService.GetFoos(); 
    } 
} 

Quando ho risolvere il mio MainViewModel quando chiamo

SimpleIoc.Default.GetInstance<MainViewModel>() 

ciò che accade internamente è che SimpleIoc controlla se il MainViewModel ha delle dipendenze (parametri nel suo costruttore). Quindi tenta di risolvere questi parametri osservando le interfacce che sono state registrate con esso. Lo fa in modo ricorsivo, quindi se DataService avesse una dipendenza, sarebbe istanziato e passato al costruttore DataService anche quando veniva istanziato.

Perché dovrei fare tutto questo?

  1. Fai le tue lezioni facilmente verificabili unità
  2. Fai interfaccia-driven codice. Ciò significa che stai facendo riferimento alle interfacce anziché alle classi concrete
  3. Rendi il tuo codice univoco. Ciò significa che qualcuno può cambiare l'implementazione di un'interfaccia e le classi che consumano quell'interfaccia non si preoccupano e non devono essere ricodificate.
  4. Risolvi le dipendenze delle classi in modo automatico.
  5. In MVVM Light, vedrai che può dire quando è in esecuzione in modalità progettazione (ViewModelBase.IsInDesignModeStatic), ciò significa che puoi creare servizi in fase di progettazione per fornire i tuoi dati viewmodels in modo che la tua vista in Visual Studio contenga dati reali .
+0

Ottima suddivisione e risposta all'argomento. Grazie. – usefulBee

+0

Perfetto, ho risparmiato un sacco di tempo. – Ahmed

+1

... e se vi siete mai chiesti se il vostro contributo avrebbe importato anni lungo la linea, sì lo fa. Questo è esattamente il tipo di guasto e di passaggio che mi ha aiutato a capire cosa sta succedendo. Grazie! – Fred

1

MVVM Light ha molte funzioni interessanti ma mi sembra che il localizzatore di servizio crei una dipendenza indesiderata delle viste sui modelli di visualizzazione. Idealmente, mi piacerebbe avere ViewModelLocator nella libreria A, i modelli di visualizzazione nella libreria B e le viste nella libreria C. Quindi posso combinarli come necessario per i progetti futuri. Tuttavia, nella progettazione di MVVM Light, per quanto posso vedere, le viste (Libreria C) avranno sempre una dipendenza da ViewModelLocator (questo è ok) ma poiché ViewModelLocator (Libreria A) avrà sempre una dipendenza dal visualizzare i modelli (Libreria B), quindi le viste dipenderanno sempre dai modelli di vista (questo non va bene perché una vista ora deve includere tutte le librerie di modelli di viste che è stata mai usata con tutti i prodotti).

Credo che Prism aggiri questo problema utilizzando le chiavi di stringa in qualche modo. Mi sto perdendo qualcosa?

Oops! Penso di aver appena risposto alla mia domanda. La soluzione è rendere la libreria A, il ServiceLocator, specifica per una particolare soluzione (prodotto). Quindi contiene un riferimento ai modelli di visualizzazione solo per quella soluzione. Quindi le viste dipendono da questo ServiceLocator che a sua volta dipende da tutti i modelli di visualizzazione per quel prodotto. Il risultato finale è che le viste dipendono solo dai modelli di viste con cui verrà utilizzato per quel prodotto. Non c'è alcun problema con il fatto che stiamo duplicando ServiceLocator per ogni soluzione perché questo modulo contiene solo il codice specifico per la soluzione. I componenti di ServiceLocator come la classe SimpleIoc sono, ovviamente, comuni a tutte le soluzioni, ma questi sono stati scomposti in classi riutilizzabili che invochiamo in ServiceLocator.

Per riassumere le cose, il problema che sto cercando di risolvere è supporre che una soluzione abbia 6 modelli di vista, quattro dei quali sono strettamente correlati e due dei quali sono strettamente correlati. Creiamo quindi due assiemi, ciascuno contenente i modelli di vista strettamente correlati. Supponiamo di progettare un prodotto che utilizza un set di modelli di visualizzazione e la soluzione è progettata per eseguire Windows 8. Ora le viste sono tutte diverse e vogliamo riutilizzare solo un set (assieme) di modelli di vista. Quindi creiamo solo un nuovo assembly ServiceLocator che punta a questo assieme di modelli di viste e anche a tutti gli altri di cui abbiamo bisogno. Le nuove viste di Windows 8 ora dipendono da questo nuovo assembly ServiceLocator e solo dai modelli di visualizzazione utilizzati nel nostro nuovo prodotto (soluzione).

Problemi correlati