2010-09-22 18 views
5

nel mio WPF UI, io uso RoutedCommands che mi riferisco a mio XAML tramite il seguente codice:implementazione WPF personalizzato ICommand e l'evento CanExecuteChanged

Command="viewModel:MessageListViewModel.DeleteMessagesCommand" 

non mi piace questo link statico per la mia classe ViewModel , credo che questo non è bello come la creazione di un'implementazione personalizzata ICommand e utilizzare una sintassi simile alla seguente

Command="{Binding DeleteMessagesCommand}" 

dopo aver creato uno, ho notato un grave inconveniente di quello che ho fatto: RoutedCommands utilizzano il CommandManager e (in qualche modo è completamente opaco per me) fuoco l'evento CommandManager.RequerySuggested, in modo che il loro metodo CanExecute venga richiesto automaticamente. Per quanto riguarda la mia implementazione personalizzata, CanExecute viene attivato una sola volta all'avvio e mai più dopo.

Qualcuno ha una soluzione elegante per questo?

risposta

8

Basta implementare l'evento CanExecuteChanged come segue:

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

Quando si assegna il comando per un controllo, si sottoscrive l'evento CanExecuteChanged. Se si "reindirizza" all'evento CommandManager.RequerySuggested, il controllo verrà notificato ogni volta che viene attivato CommandManager.RequerySuggested.

+0

Grazie mille per questo grande e concisa risposta! Funziona come un fascino. Per caso, sai quando e perché RequerySuggested viene licenziato? –

+1

Non esattamente, ma sembra che capiti molto spesso ... –

+0

OK, grazie mille ancora! –

0

Preferisco di gran lunga l'implementazione DelegateCommand di Prism per il binding di modelmodel (http://msdn.microsoft.com/en-us/library/ff654132.aspx). Puoi richiamare CanExecute() su ogni invoker di comandi chiamando RaiseCanExecuteChanged su di esso.

semplice esempio di utilizzo:

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

Grazie per l'idea, ma - come abbiamo appreso - "con un grande potere derivano grandi responsabilità" ... –

+0

Spiacente, premuto Invio troppo presto. Quello che voglio dire è: pur dandomi la possibilità di farlo, mi costringe anche a farlo per essere informato. –

Problemi correlati