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
.
Sì, ma solo se non si sta ottimizzando prematuramente. – Will
Il tuo commento sarà un po 'ambiguo. – Tyrsius
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