In questi giorni abbiamo iniziato lo sviluppo di un nuovo progetto con WPF. Quale contesto migliore per iniziare a valutare MVVMLight, un framework veramente "leggero" che mette a disposizione tutto l'essenziale per lo sviluppo di applicazioni WPF/Silverlight sfruttando il pattern MVVM, di cui tutti parlano un gran bene...
In prima battuta il framework mi sembra proprio ben fatto e, soprattutto, veramente poco invasivo, a differenza, per esempio, di quanto avviene con Prism che, seppur approcciando una problematica più complessa (UI composition) mette a disposizione una "rete" di classi troppo intricata e difficilmente "spacchettabile" (ma questo sarà oggetto di un altro post)
Tornando a noi...facendomi guidare dai test e dal ritmo che mi garantiscono ho iniziato a creare ViewModel ed aggiungerne funzionalità. Ed ecco sopraggiungere un piccolo, fastidioso problema: volendo testare che, a fronte di una particolare condizione, venisse scatenata la rivalutazione del metodo CanExecute di un command ho scritto il, solito, seguente test:
Con la seguente implementazione:
Con mia somma sorpresa, il test non passa...no bello!!! Piccola nota di colore: sostituendo l'implementazione di RelayCommand di MVVMLight con l'implementazione data da Prism (DelegateCommand) il test passa.
Indagando, grazie anche all'aiuto di Corrado (thanks a lot), abbiamo trovato l'inghippo: l'implementazione di RelayCommand per WPF basa il suo funzionamento su CommandManager. Il tutto a runtime funziona egregiamente, ma in fase di unit-test, per esempio, in cui nessun controllo "consuma" il command esposto dal viewmodel, l'engine di WPF non ritiene necessario rivalutare il metodo CanExecute del command stesso, nonostante venga forzata la chiamata al metodo RaiseCanExecuteChanged.
Come risolvere il problema? Prendere l'implementazione di RelayCommand per Silverlight che funziona egregiamente, oppure utilizzare un'altra implementazione di ICommand (per esempio i DelegateCommand di Prism) fino a quando Laurent non fixerà il problema (dovrebbe essere già stato avvisato, giusto Corrado?)