Architettura Model-View-ViewModel in un'applicazione WPF

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

Command pattern

Ogni applicazione ha solitamente un'interazione con l'utente e per farlo si usano i controlli presenti in WPF che reagiscono a mouse, stylus e tastiera. In WPF è presente un'interfaccia ICommand il cui scopo è rappresentare un comando, restituire la possibilità di eseguirlo e eseguire effettivamente l'operazione, ed è così definita:

public interface ICommand 
{ 
  event EventHandler CanExecuteChanged; 
  bool CanExecute(object parameter); 
  void Execute(object parameter); 
}

Inoltre, tramite l'interfaccia ICommandSource, i controlli presenti in WPF possono essere associati ai comandi, abilitarsi o meno in funzione di CanExecute ed eseguire il metodo Execute sul loro evento predefinito. Questi controlli sono Button, MenuItem, CheckBox, RadioButton, HyperLink, KeyBinding e MouseBinding e sebbene in parte limitati sulla possibilità di eseguire il comando solo nel loro evento predefinito (esempio: il click su Button), permettono di separare il codice dall'interfaccia, di avere un comportamento automatico di posso o non posso eseguire, e di testare il comando stesso senza provare l'interfaccia.

L'idea applicata al ViewModel quindi, è quella di esporre tramite esso una serie di comandi di competenza così da poter essere sfruttati una o più volte all'interno della View. Ad esempio, il comando per il refresh dei thread, può essere esposto tramite una proprietà RefreshCommand inizializzata nel costruttore:

private ICommand _refreshCommand; 
 
public MainWindowViewModel() 
{ 
  _refreshCommand = new RelayCommand(p => RefreshAsync(), p => !this.IsLoading); 
} 
 
public ICommand RefreshCommand 
{ 
  get { return _refreshCommand; } 
}

La classe RelayCommand è creata appositamente e riceve un delegate da chiamare per l'esecuzione del comando e un delegate da chiamare per conoscere se è possibile chiamare il comando. In questo caso si valuta la proprietà IsLoading così da non eseguire il refresh se è già in corso tale operazione. Diversamente da quanto si può essere abituati, non si usano i RoutedCommand o i RoutedUICommand poiché questi si affidano ai CommandBinding e richiedono che dal markup si debba specificare i delegate da eseguire, inquinando l'approccio MVVM. Ecco come è definita la classe RelayCommand:

public class RelayCommand : ICommand 
{ 
 
  readonly Action<Object> _execute; 
  readonly Predicate<Object> _canExecute; 
 
  public RelayCommand(Action<Object> execute, Predicate<Object> canExecute) 
  { 
    if (execute == null) 
      throw new ArgumentNullException("execute"); 
 
    _execute = execute; 
    _canExecute = canExecute; 
  } 
 
  [DebuggerStepThrough] 
  public bool CanExecute(object parameter) 
  { 
    return _canExecute == null ? true : _canExecute(parameter); 
  } 
 
  public event EventHandler CanExecuteChanged 
  { 
    add { CommandManager.RequerySuggested += value; } 
    remove { CommandManager.RequerySuggested -= value; } 
  } 
 
  public void Execute(object parameter) 
  { 
    _execute(parameter); 
  } 
}

Interessante l'evento RequerySuggested della classe statica CommandManager che permette di conoscere quando il motore di gestione dei comandi invalida lo stato di essi e rivaluta tutte le proprietà CanExecute. In questo modo tutti gli elementi dell'interfaccia cambiano e, per esempio, un pulsante si disabilita se non è possibile eseguire il comando ad esso associato. La rivalutazione di tale proprietà avviene in automatico ogni qual volta l'applicazione riceve un input da tastiera, la pressione del mouse, perde o riceve il focus. Qualora la si voglia forzare è possibile chiamare CommandManager.InvalidateRequerySuggested.

Nella View infine il comando può essere sfruttato una o più volte semplicemente con un'espressione di Binding.

<ToolBarTray DockPanel.Dock="Top"> 
  <ToolBar> 
    <Button Command="{Binding RefreshCommand}">Refresh</Button> 
  </ToolBar> 
</ToolBarTray>

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