La interfaz ICommand
es la siguiente:
public interface ICommand
{
// two methods
bool CanExecute(object parameter);
void Execute(object parameter);
// one event
event EventHandler CanExecuteChanged;
}
El evento CanExecuteChanged
debe plantearse cualquier momento que desee para indicar que el método CanExecute
debe comprobarse/llamado por WPF. Quien implementa ICommand
debe plantear el evento y quien necesite actualizar el estado de botón habilitado en la GUI (el sistema WPF) debe registrarse y manejar el evento y llama al CanExecute
.
En la clase de Josh Smith RelayCommand
, que utiliza WPF incorporado en CommandManager
clase para elevar CanExecuteChanged
:
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
En esencia, de WPF CommandManager
es un producto único que se escucha de todo tipo de eventos enrutados: KeyUpEvent, MouseUpEvent, etc ... y luego les dice a todos "hey pasó algo interesante" al plantear su evento RequerySuggested
. Por lo tanto, si usa RelayCommand
, se llamará a su CanExecute
cada vez que CommandManager
cree que algo interesante sucedió en la GUI (incluso si no tiene nada que ver con su colección). Si tiene 50 comandos, cada vez que enciende, vuelve a verificar los 50 comandos. Así que sí, este podría ser un problema de rendimiento. Sin embargo, si su lógica en su método CanExecute
es realmente simple, probablemente no sea un problema. Punto de partida: no realice llamadas de API de red o de base de datos en el método CanExecute
.
La alternativa a la que lleva a cuestas fuera CommandManager.RequerySuggested
para generar el evento ICommand.CanExecuteChanged
es a liar su propia versión de RelayCommand
donde hace su propia comprobación y elevar CanExecuteChanged
manualmente, o buscar en la clase del marco Prisma DelegateCommand
, donde no vinculan en CommandManager
y tiene que plantear manualmente el evento CanExecuteChanged
, que probablemente podría hacer creando un oyente para PropertyChanged
y luego levantando CanExecuteChanged
en el comando.
Estoy de acuerdo con @Will más arriba. RelayCommand
probablemente funcionará más del 80% del tiempo sin problemas. Si comienza a encontrar problemas de rendimiento, puede crear su propia versión de RelayCommand o usar el Prisma DelegateCommand
y subir el CanExecuteChanged
manualmente.
Sí, pero solo si no está optimizando prematuramente. – Will
¿Tu comentario es un poco ambiguo? – Tyrsius
Will, tampoco entiendo completamente. Mi validación es una iteración de aproximadamente 200 objetos: una vista en árbol. Simplemente comprueba una propiedad simple y no consume mucho tiempo cuando se ejecuta una vez. Mi preocupación es si el CanExecute se dispara repetidamente haciendo que el código sea lento. ¿Alguien puede por favor arrojar algo de luz? – ganeshran