2011-09-07 14 views
5

Cuáles son las implicaciones de rendimiento del uso de CanExecuteCommand del objeto ICommand. ¿El método se ejecuta una y otra vez?¿Hay alguna implicancia de rendimiento con CanExecuteCommand?

Necesito iterar a través de una colección de aproximadamente 200 objetos en función de la cual se decidió si el botón vinculado al Comando debería estar habilitado. ¿El CanExecuteCommand conseguir ejecuta repetidamente que hará que mi solicitud lento

+4

Sí, pero solo si no está optimizando prematuramente. – Will

+0

¿Tu comentario es un poco ambiguo? – Tyrsius

+0

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

Respuesta

13

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.

+0

Respuesta relacionada aquí: http://stackoverflow.com/questions/6634777/what-is-the-actual-task-of-canexechangechanged-and-commandmanager-requerysuggested – Kendrick

+0

Gracias Kendrick y Will, sus respuestas lo resumieron por mí. Lo pondré en CanExecute y buscaré cualquier retraso de rendimiento. Si encuentro uno, entonces veré otras implementaciones – ganeshran

0

Para futuros googlers: He creado una implementación de comandos algo diferente. Por un lado, está vinculado al evento OnPropertyChanged de la clase ViewModelBase, pero también permite que View Model eleve el evento CanExecuteChanged para todas las instancias Command dentro de él, independientemente de un cambio en la propiedad, como en el caso de One Way Para el escenario vinculante de origen. esta solución es parte del ensamblado PerrypheralFrameowrk.WPF, disponible en nuget y codeplex. Búscalo. La wiki codeplex tiene una documentación detallada, y también lo hacen las clases en el ensamblado.

Cuestiones relacionadas