Architettura Model-View-ViewModel in un'applicazione WPF

7 pagine in totale: <<Indietro 1 2 3 [4] 5 6 7 Avanti >>

Asynchronous Pattern

Il comando di refresh descritto nel paragrafo precedente si appoggia sulla proprietà IsLoading, perché si vuole ipotizzare che l'esecuzione dell'eventuali query o chiamatal servizio, possano impiegare qualche secondo e non si vuole rendere bloccante l'interfaccia. Nel metodo RefreshAsync occorre quindi invocare in asincrono ForumManager.GetAllThreads, per esempio attraverso il ThreadPool e cambiare IsLoading ad inizio e a fine operazione. La lista dei thread ottenuta deve essere poi convertita in ThreadPostViewModel e popolare la proprietà Threads così da poter permette la visualizzazione e l'adozione di una vista per ogni thread. Tale proprietà è di tipo ObservableCollection e ciò significa che con l'interfaccia INotifyCollectionChanged questa è in grado di notificare il motore di Binding quando si aggiungono o si tolgono elementi da essa. Una ListBox quindi, è in grado di adattare gli elementi che contiene monitorando la proprietà Threads.

Tutto questo automatismo comporta però un problema dovuto alla gestione dell'interfaccia grafica. Ogni modifica agli elementi dell'interfaccia, va effetuata sul thread UI attraverso il Dispatcher che ha il compito di gestire la coda di operazioni da eseguire per il disegno dell'interfaccia, le animazioni ecc. Per gli scopi che il pattern MVVM si propone però, sfruttare direttamente il Dispatcher e porsi questa problematica in realtà vanno in conflitto con esso.

In aiuto vengono alcune classi introdotte con il .NET Framework 2.0 e in particolare con il tipo AsyncOperationManager che attraverso il metodo CreateOperation permette di rappresentare un'operazione e di notificare la sua conclusione attraverso un delegate che viene invocato attraverso il SynchronizationContext corrente. Quest'ultimo varia a seconda dell'ambiente in cui gira il codice e può assumere forma nel Dispatcher di WPF, di Silverlight o nella message pump delle WinForm, garantendo di poter scrivere un ModelView il più indipendente possibile.

Di seguito quindi il metodo RefreshAsync:

public void RefreshAsync() 
{ 
  // Notifico l'esecuzione asincrona 
  this.IsLoading = true; 
  // Creo un'operazione che rappresenta il refresh 
  AsyncOperation refreshOperation = AsyncOperationManager.CreateOperation(null); 
 
  // Invoco in asincrono 
  ThreadPool.QueueUserWorkItem(delegate 
  { 
    try 
    { 
      IEnumerable<ThreadPost> threads = ForumManager.GetAllThreads(); 
 
      // Invoco sul thread UI la funzione 
      refreshOperation.PostOperationCompleted(OnRefreshAsyncCompleted, threads); 
    } 
    catch (Exception) 
    { 
      refreshOperation.PostOperationCompleted(OnRefreshAsyncFailed, null); 
    } 
  }, refreshOperation); 
}

Il metodo OnRefreshAsyncFailed, invocato sul threadUI in caso di errori, non fa altro che impostare IsLoading a false e invalidare lo stato dei comandi.

private void OnRefreshAsyncFailed(object arg) 
{ 
  this.IsLoading = false; 
  CommandManager.InvalidateRequerySuggested(); 
}

Il metodo OnRefreshAsyncCompleted invece prepara i thread e reimposta lo stato:

private void OnRefreshAsyncCompleted(object arg) 
{ 
  this.IsLoading = false; 
  CommandManager.InvalidateRequerySuggested(); 
 
  // Preparo il ViewModel per i thread 
  IEnumerable<ThreadPost> threads = (IEnumerable<ThreadPost>)arg; 
  this.Threads.Clear(); 
  foreach (ThreadPost tp in threads) 
    this.Threads.Add(new ThreadPostViewModel(tp)); 
}

Eventualmente, è possibile oltre a PostOperationCompleted, invoicare solamente il metodo Post per non terminare l'operazione, ma semplicemente notificare il progresso di un'operazione, oppure esporre un evento RefreshAsyncCompleted da invocare sempre con Post o PostOperationCompleted per facilitare l'utilizzo di eventuali EventTrigger nella View.

7 pagine in totale: <<Indietro 1 2 3 [4] 5 6 7 Avanti >>

Attenzione: Questo articolo contiene un allegato

Contenuti dell'articolo

Commenti

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.



Segnala su: Facebook MSDN Social Twitter Segnalo Wikio Diggita Technorati Stumbleupon Google Yahoo FriendFeed Delicious Furl

IL CONTENUTO
TUTORIALS
TOP TEN ARTICOLI
ARTICOLI VIA E-EMAIL

Iscriviti alla nostra newsletter nuoviarticoli per ricevere via e-mail le notifiche!

MEDIA
IN EVIDENZA
MISC