2011-09-07 18 views
5

Quali sono le implicazioni sulle prestazioni dell'utilizzo di CanExecuteCommand dell'oggetto ICommand. Il metodo viene eseguito più e più volte?Ci sono implicazioni sul rendimento con CanExecuteCommand?

Ho bisogno di ripetere una collezione di circa 200 oggetti in base alla quale è stato deciso se il pulsante associato al comando deve essere abilitato? Fa il CanExecuteCommand vengono eseguiti più volte che renderà la mia domanda rallentare

+4

Sì, ma solo se non si sta ottimizzando prematuramente. – Will

+0

Il tuo commento sarà un po 'ambiguo. – Tyrsius

+0

Will, anche io non capisco completamente. La mia convalida è un'iterazione di circa 200 oggetti: una visualizzazione ad albero. Controlla solo una proprietà semplice e non richiede molto tempo quando viene eseguita una volta. La mia preoccupazione è se CanExecute viene attivato ripetutamente rendendo il codice lento. Qualcuno può per favore gettare un po 'di luce – ganeshran

risposta

13

L'interfaccia ICommand è la seguente:

public interface ICommand 
{ 
    // two methods 
    bool CanExecute(object parameter); 
    void Execute(object parameter); 

    // one event 
    event EventHandler CanExecuteChanged; 
} 

L'evento CanExecuteChanged dovrebbe essere sollevata in qualsiasi momento si desidera indicare che il metodo CanExecute deve essere controllato/chiamato da WPF. Chiunque implementi ICommand deve generare l'evento e chiunque debba aggiornare lo stato attivato tramite pulsante sulla GUI (il sistema WPF) deve registrarsi e gestire l'evento e chiama CanExecute.

In classe di Josh Smith RelayCommand, egli utilizza WPF di built-in CommandManager classe per aumentare CanExecuteChanged:

public event EventHandler CanExecuteChanged 
{ 
    add { CommandManager.RequerySuggested += value; } 
    remove { CommandManager.RequerySuggested -= value; } 
} 

In sostanza, di WPF CommandManager è un Singleton che l'ascolto per tutti i tipi di eventi indirizzati: KeyUpEvent, MouseUpEvent, ecc ... e poi dice a tutti "hey è successo qualcosa di interessante" sollevando il suo evento RequerySuggested. Quindi se stai utilizzando RelayCommand, il tuo CanExecute verrà chiamato ogni volta che CommandManager pensa che qualcosa di interessante sia successo sulla GUI (anche se non ha nulla a che fare con la tua collezione). Se hai 50 comandi, ogni volta che digiti, ricontrollare tutti e 50 i comandi. Quindi sì, questo potrebbe essere un problema di prestazioni. Tuttavia, se la logica del tuo metodo CanExecute è davvero semplice, probabilmente non è un problema. Punto da asporto: non effettuare chiamate API di database o di rete nel metodo CanExecute.

L'alternativa a piggybacking off CommandManager.RequerySuggested per generare l'evento ICommand.CanExecuteChanged è quello di roll-your-own versione di RelayCommand dove si fa il proprio controllo e sollevare CanExecuteChanged manualmente, o guardare la classe del framework Prism DelegateCommand, dove non legano in CommandManager e devi aumentare manualmente l'evento CanExecuteChanged, che probabilmente potresti fare creando un listener per PropertyChanged e quindi aumentando il comando CanExecuteChanged.

Sono d'accordo con @Sempre tuttavia. RelayCommand probabilmente funzionerà oltre l'80% delle volte senza problemi. Se si inizia a rilevare problemi di prestazioni, è possibile creare la propria versione di RelayCommand o utilizzare il Prisma DelegateCommand e aumentare manualmente CanExecuteChanged.

+0

Risposta correlata qui: http://stackoverflow.com/questions/6634777/what-is-the-actual-task-of-canexecutechanged-and-commandmanager-requerysuggested – Kendrick

+0

Grazie Kendrick e Will, le tue risposte lo hanno riassunto per me. Lo inserirò in CanExecute e cercherò qualsiasi ritardo nelle prestazioni. Se trovo uno, guarderò ad altre implementazioni – ganeshran

0

Per i googler futuri: Ho creato un'implementazione di comando in qualche modo diversa. Ad esempio, è associato all'evento OnPropertyChanged della classe ViewModelBase, ma consente anche al View Model di aumentare l'evento CanExecuteChanged per tutte le istanze di Command al suo interno, indipendentemente da una modifica della proprietà, ad esempio nel caso di One Way Allo scenario di associazione di origine. questa soluzione è una parte del PerrypheralFrameowrk.WPF Assembly, disponibile su nuget e codeplex. Guarda su Il wiki di codeplex ha una documentazione dettagliata, così come le classi nell'assembly.

Problemi correlati