|
WPF MVVM : Les RelayCommands
Richard Clark
30/07/09
(Vu
3041)
Série d'articles sur l'approche MVVM pour WPF/Silverlight Maintenant que nous avons vu les liaisons entre les View et les ViewModel, nous allons voir comment gérer les commandes. Dans une approche "traditionnelle", on s'abonne à l'évènement "Click" du bouton. Dans une approche un peu plus organisée, on crée une Routed(UI?)Command avec WPF. Mais je rappele que l'approche MVVM demande à ce que le minimum de code soit implémenté dans l'UI, donc dans notre View (UserControl). On ne peut donc pas s'abonner à l'évènement du clic sur le bouton ni aux ExecuteCommand et CanExecuteCommand d'une RouteCommand. Heureusement, Josh Smith a crée les RelayCommand (DelegateCommand dans Prism). RelayCommand La classe RelayCommand, qui implémente ICommand, permet d'exposer une ICommand comme une propriété d'un objet. Une RelayCommand possède essenciellement deux propriétés :
Donc pour utiliser une RelayCommand, vous devez définir une ou deux méthodes (la méthode CanExecuteCommand est optionnelle) qui seront appelés par le mécanisme d'implémentation des ICommand dans WPF. On peut donc prototyper notre ViewModel avec de nouvelles propriétés de type RelayCommand : public PersonneViewModel()
{
if (IsInDesignMode)
{
this.Personne = new Personne() { Nom = "Clark", Prenom = "Richard" };
}
else
{
this.Personne = new Personne() { Nom = "Gates", Prenom = "Billou" };
CreateSaveCommand();
}
}
public const string PersonnePropertyName = "Personne";
private Personne _personne = null;
public Personne Personne
{
get{return this._personne;}
private set
{
if (this._personne == value)
{
return;
}
this._personne = value;
RaisePropertyChanged(PersonnePropertyName);
}
}
private void CreateSaveCommand()
{
SaveCommand = new RelayCommand(ExecuteSaveCommand, CanExecuteSaveCommand);
}
public ICommand SaveCommand { get; internal set; }
public void ExecuteSaveCommand()
{
System.Diagnostics.Debug.Write("ExecuteSaveCommand");
}
public bool CanExecuteSaveCommand()
{
if (this.Personne == null || string.IsNullOrEmpty(this.Personne.Nom) || string.IsNullOrEmpty(this.Personne.Prenom))
return false;
return true;
}
La méthode CreateSaveCommand est appelée dans le constructeur et crée notre RelayCommand. La méthode CanExecuteSaveCommand est appelée par le moteur WPF (voir CommandManager) et retourne si la commande peut être exécutée ou non. La méthode ExecuteSaveCommand sera appelée à l'exécution de la commande. Pour résumer, notre ViewCommand possède donc les propriétés suivantes :
Notre RelayCommand est une propriété comme une autre ;-) Moralité, dans notre View, nous pouvons nous binder à cette propriété. Ajoutons un bouton : <Button Content="Save" Command="{Binding SaveCommand}" />
RelayCommand<T> Il se peut également que vous ayez besoin de commande avec un paramètre. Par exemple une commande de type Recherche qui a comme argument le texte saisie par l'utilisateur pour sa recherche. Dans ces cas là, vous allez utiliser la version "typée" de RelayCommand : RelayCommand<T>. Elle se définie exactement de la même façon sauf que vos méthodes doivent attendre un paramètre. Ce qui nous donne par exemple : private void CreateSearchCommand()
{
SearchCommand = new RelayCommand<string>(ExecuteSearchCommand, CanExecuteSearchCommand);
}
public ICommand SearchCommand { get; internal set; }
public void ExecuteSearchCommand(string param)
{
// allez, cherche le chien, chien...
}
public bool CanExecuteSearchCommand(string param)
{
return true;
}
Quid de commandes exécutées lors d'un évènement ? Dans la situation actuelle, notre ViewModel possède donc une ou plusieurs commandes de type RelayCommand qui sont exposées comme propriétés. On peut donc les binder avec notre interface, notre view : <Button Content="Save" Command="{Binding SaveCommand}" />
Mais quid si l'on veut exécuter la commande SaveCommand quand un évènement particulier se déclenche ? Par exemple une sauvegarde automatique toutes les 5mn ? Une solution est de créer une classe qui définie deux propriétés attachées qui sont :
Je vous invite à lire l'exemple donné par Thomas Lebrun sur son blog : http://blogs.developpeur.org/tom/archive/2009/04/14/wpf-comment-actionner-une-commande-wpf-lorsqu-un-v-nement-est-d-clench.aspx C'est élégant et cela permet de tout mettre dans le Xaml. Personnellement, je trouve au contraire qu'il est justifiable de mettre du code dans le code behind pour appeler explicitement la commande, surtout que cela présente un avantage de taille : vous pouvez appeler la méthode CanExecute avant d'appeler la méthode Execute. Conclusion Nous avons vu comment créer une View, un ViewModel, ajouter des propriétés de type ICommand à notre ViewModel, il ne nous reste plus qu'à orchester tout cela entre les différentes View de notre UI. Vous pouvez télécharger le code de cet article ici. Richard Clark
Vos commentaires
Vous devez être identifié pour pouvoir commenter l'article. |

