7

Ho un modello di visualizzazione con un costruttore che richiede un servizio. Sto usando MvvmLight di GalaSoft che utilizza un localizzatore di servizi per collegare la vista al modello di visualizzazione.MVVM visualizzazione modello e inizializzazione dati asincroni

SimpleIOC gestisce il servizio per il costruttore viewmodels, ma in qualche modo devo compilare il mio viewmodel con i dati di un'origine dati. Il mio ViewModel sembra un così: -

public class MainPageViewModel : ViewModelBase 
{ 
    private readonly GroupService _groupService; 
    private readonly GroupFactory _groupFactory; 
    private readonly ObservableCollection<GroupVM> _groupVms = new ObservableCollection<GroupVM>(); 


    public MainPageViewModel(Domain.Services.GroupService groupService, VMFactories.GroupFactory groupFactory) 
    { 
     _groupService = groupService; 
     _groupFactory = groupFactory; 
    } 

    public async Task Init() 
    { 
     var groups = await _groupService.LoadGroups(); 
     foreach (var group in groups) 
     { 
      GroupVms.Add(_groupFactory.Create(group)); 
     } 
    } 

    public ObservableCollection<GroupVM> GroupVms { get { return _groupVms; } } 
} 

In qualche modo il metodo init ha bisogno di essere chiamato atteso, ma non so il modo migliore per fare questo? Mi vengono in mente tre opzioni: -

  1. mi basta chiamare Init sul costruttore, ma non attendere (lo so questo è davvero una cattiva pratica)
  2. chiamo Init sull'oggetto ViewModelLocator, ma dal momento che non ci riesco restituire un compito Non riesco ancora ad attendere l'init
  3. Sul carico della vista getto il DataContext su una sorta di IAsyncViewmodel e attendo il metodo init.

Ho usato l'opzione 3 in un precedente progetto di Windows 8 store ma mi sembra sbagliato. Qualche consiglio sarebbe molto apprezzato!

Grazie

Ross

risposta

7

Sono curioso di sapere perché non si aspetta una chiamata asincrona come una cattiva pratica. A mio parere, non è male finché sai cosa significa, che la chiamata verrà eseguita in background e potrebbe tornare in qualsiasi momento.

In genere quello che faccio è che chiamo il metodo async nel costruttore per lo scopo di creazione dei dati di ora di progettazione e non lo attendo. Mi occupo solo di aumentare gli eventi PropertyChanged e CollectionChanged laddove necessario per aggiornare i binding, e questo fa proprio il trucco.

Acclamazioni Laurent

+0

Un buon punto, era più "una di quelle" cose che avevo preso, ma che non avevo davvero pensato. Ecco un po 'più di informazioni su: http://stackoverflow.com/questions/7261173/c-sharp-start-async-method-within-object-constructor-bad-practice Fondamentalmente è perché quando l'oggetto è costruito è ancora " fare cose "forse inaspettatamente, in più è molto difficile gestire le eccezioni che potrebbero verificarsi. Ho provato entrambi i modi, e penso di preferire l'init nel costruttore, ma non sono ancora sicuro! –

+0

suggerimento: per evitare che gli "squigglies" in Visual Studio assegnino il valore dell'attività restituita a una variabile fittizia –

1

Io non sono come familiarità con MvvmLight come ero una volta, ma ho cercato di fare con async costruttori in una varietà di modi.

L'opzione (1) presenta complessità di gestione degli errori. L'opzione (3) impone che InitAsync sia accessibile.

preferisco un approccio async fabbrica (per esempio, l'opzione (2), in cui il DataContext sarebbe rimasto fino null l'inizializzazione VM completa), ma suona come ViewModelLocator non funzionerà per questo. Quindi (per ora) devi scegliere tra uno stabilimento async che non usa IoC e una delle altre opzioni (1 o 3) che non sono l'ideale.

Personalmente, avrei buttato fuori IoC per VM/View binding (non utilizzo mai IoC per quello, le mie visualizzazioni dipendono dalle mie macchine virtuali) e uso un metodo factory async. Tuttavia, le altre opzioni sono perfettamente valide se vuoi stare con IoC. Per le macchine virtuali, penso che l'opzione (1) sarebbe leggermente migliore rispetto all'opzione (3) se hai sempre avuto un livello superiore try/catch nei tuoi metodi InitAsync.

+0

Grazie, lascio aperta la questione per un po 'di più come mi piacerebbe sentire altri popoli opinioni su questo. –

Problemi correlati