2010-09-22 20 views
5

en mi WPF UI, que utilizan RoutedCommands los que me refiero en mi xaml mediante el siguiente código:aplicación WPF personalizado ICommand y el evento CanExecuteChanged

Command="viewModel:MessageListViewModel.DeleteMessagesCommand" 

no me gusta este enlace estática a mi clase ViewModel , creo que esto no es tan agradable como la creación de una aplicación ICommand costumbre y utilizar una sintaxis como la siguiente

Command="{Binding DeleteMessagesCommand}" 

después de haber creado uno, noto una desventaja importante de lo que he hecho: RoutedCommands utilizan el Administrador de comandos y (de alguna manera eso es completamente opaco para mí) fuego el evento CommandManager.RequerySuggested, para que su método CanExecute se vuelva a consultar automáticamente. En cuanto a mi implementación personalizada, CanExecute solo se activa una vez al inicio y nunca más después de eso.

¿Alguien tiene una solución elegante para esto?

Respuesta

8

Sólo implementar el evento CanExecuteChanged de la siguiente manera:

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

Al asignar el comando a un control, que se ajuste al caso CanExecuteChanged. Si lo "redirige" al evento CommandManager.RequerySuggested, se notificará el control siempre que se active CommandManager.RequerySuggested.

+0

Muchísimas gracias por este gran y concisa respuesta! Funciona de maravilla. ¿Sabe, por casualidad, cuándo y por qué se lanza RequerySuggested? –

+1

No exactamente, pero parece que sucede muy a menudo ... –

+0

OK, ¡muchas gracias de nuevo! –

0

Prefiero mucho la implementación DelegateCommand de Prism para el enlace de viewmodel (http://msdn.microsoft.com/en-us/library/ff654132.aspx). Puede invocar CanExecute() en cada invocador de comandos llamando a RaiseCanExecuteChanged en él.

ejemplo de uso simple:

public class ViewModel 
{ 
    public ViewModel() 
    { 
     Command = new DelegateCommand<object>(x => CommandAction(), x => CanCommandAction()); 
    } 

    bool state; 

    public void ChangeState(bool value) 
    { 
     state = value; 
     Command.RaiseCanExecuteChanged(); 
    } 

    public DelegateCommand<object> Command {get; private set;} 

    private void CommandAction() 
    { 
     //do smthn 
    } 

    private bool CanCommandAction() { return true == state; } 
} 

//and binding as usual 
Command="{Binding Command}" 
+0

Gracias por la idea, pero, como hemos aprendido, "con gran poder viene una gran responsabilidad" ... –

+0

Lo sentimos, presionamos Ingrese demasiado pronto. Lo que quiero decir es: si bien me da la oportunidad de hacerlo, también me obliga a hacerlo para recibir una notificación. –