|
WPF MVVM : Event Aggregator
Richard Clark
30/07/09
(Vu
2649)
Série d'articles sur l'approche MVVM pour WPF/Silverlight Nous savons maintenant créer des vues (view), créer des propriétés de type RelayCommand, il nous faut maintenant pouvoir communiquer entre les différentes vues de notre interface. Imaginons par exemple une simple fenêtre contenant une barre d'outils et une grille affichant la liste des personnes : Dans notre exemple, nous avons en réalité deux vues :
Ce que l'on veut, c'est que quand on clique sur le bouton Refresh, la liste des personnes dans la vue PersonnesView soit réactualiser. Dans des approches "traditionnelles", il faudrait que la vue PersonnesView soit au courant de l'existance de la vue "MainToolBar", donc qu'en gros, on crée une dépendance entre les deux vues. Mais si on est dans un gros projet, le développeur de la ToolBar peut être en Inde et le développeur de la grille au Guatemala (je sais pas pourquoi je parle du Guatemala, j'y suis jamais allé ;-)). Donc l'idée ici est que la ToolBar signifie que l'on souhaite rafraichir la liste des personnes. Elle annonce au monde entier : "J'aimerais bien que la liste des personnes soit rafraichie" ou "Liste des personnes à rafraichir SVP". D'un autre côté, la vue affichant la liste des personnes est à l'écoute de ce type de message. Elle écoute la radio en permanence et si il y a un message du type : "Liste des personnes à rafraichir SVP", alors elle s'exécute. On va donc mettre en place la radio qui va permettre à tout un chacun de publier l'information : "Liste des personnes à rafraichir SVP" et d'un autre côté, diffuser cette information. Messenger ou EventAggregator Dans Prism, nous avons l'eventeggregator. Dans le framework de Laurent Brunion, nous avons le Messenger. Les deux font la même chose (en gros), ie l'enregistrement des écouteurs et le dispatch des diffuseurs. Mettons nous dans la peau du diffuseur d'information, c'est-à-dire notre toolbar. Quand on clique sur le bouton Rafraichir, on veut diffuser l'information comme quoi ce serait bien de rafraichir la liste des Personnes. On va donc créer dans notre ViewModel du MainToolBar une nouvelle propriété de type commande RefreshPersonnesCommand : public class MainToolBarViewModel : ViewModelBase
{
public MainToolBarViewModel()
{
CreateRefreshPersonnesCommand();
}
#region RefreshPersonnesCommand
private void CreateRefreshPersonnesCommand()
{
RefreshPersonnesCommand = new RelayCommand(ExecuteRefreshPersonnesCommand);
}
public ICommand RefreshPersonnesCommand { get; internal set; }
public void ExecuteRefreshPersonnesCommand()
{
Messenger.Default.Broadcast(new RefreshPersonnesMessage(this));
}
#endregion
}
Ce qu'il y a de nouveau par rapport à ce que l'on a vu dans les articles précédents, c'est l'utilisation de Messenger : on diffuse (Broadcast) une information (de type RefreshPersonnesMessage). L'intérêt est que tous les écouteurs qui attendent un message de type RefreshPersonnesMessage seront notifiés de cette demande. La classe RefreshPersonnesMessage est juste une classe qui hérite de Message : public class RefreshPersonnesMessage : MessageBase
{
public RefreshPersonnesMessage(object sender) : base(sender) { }
public RefreshPersonnesMessage(object sender, object target) : base(sender, target) { }
}
On en fait juste que typer le message. Bien entendu, on peut imaginer le passage de paramètres supplémentaires via cette classe, mais pour l'instant, restons simple. L'écouteur Notre vue affichant la liste des personnes est à l'écoute des messages de rafraichissement. Si quelque part dans l'interface, quelqu'un demande le rafraichissement (ie fait un Broadcast de type RefreshPersonnesMessage), elle doit en être informée pour faire son boulot (ie rafraichir la liste des personnes). Pour cela, il faut que cette classe, dans le framework utilisé ici, implémente l'interface IMessageRecipient. Dans notre cas (PersonnesViewModel) : public void ReceiveMessage(MessageBase message)
{
RefreshPersonnesMessage msg = message as RefreshPersonnesMessage;
if (msg != null)
{
Personnes.Clear();
Personnes.Add(new Personne() { Nom = "Clark", Prenom = "Cyprien" });
}
}
Il n'y a aucunes références "en dur" entre le diffuseur de l'information et celui qui traite l'information. Tout objet peut diffuser une information (via le singleton Messenger.Default et sa méthode Broadcast) et tout IMessageRecipient peut capter cette diffusion et agir en fonction. Vous pouvez télécharger l'exemple de cet article ici. Richard Clark
Vos commentaires
Richard Clark
a dit le
30/07/09
à
22:10
Yep. Après c'est comme on préfère : l'approche déclarative ou impérative. Perso : m'en fou, les 2 me vont ;-)
Richard Clark
a dit le
30/07/09
à
22:15
Mais toujours est-il que tout le monde tourne autour du même pot, pot qui aurait pu être implémenté, présenté, dès le début de WPF.
Thomas LEBRUN
a dit le
30/07/09
à
19:24
Hello Richard,
Personnellement, j'utilise le Mediator de Marlon Grech (http://marlongrech.wordpress.com/2009/04/16/mediator-v2-for-mvvm-wpf-and-silverlight-applications/). Il fonctionne sur le même principe que l'Event Aggregator ou le Messenger mais offre l'avantage de pouvoir passer par des attributs, sur l'écouteur :) A+ Vous devez être identifié pour pouvoir commenter l'article. |

