SlideShare une entreprise Scribd logo
1  sur  41
L’architecture MVVM
MVVM Light Toolkit
Jean-Baptiste Vigneron
@jbvigneron
David Bottiau
@dbottiau
Sommaire
• Introduction
– Présentation
– MVVM Light Toolkit
– Comparaison rapide entre MVVM, MVC et MVP
• Notes pour cette présentation
• Architecture
• Les ViewModels
– Données
– Commandes
– Modes de binding
• Le ViewModelLocator
• Les Design ViewModels
• La Messagerie
Présentation
• MVVM est un patron de conception (design-pattern)
conçu à la base pour les applications .NET
• Model (Modèle) – View (Vue) – ViewModel (Vue-
Modèle)
• Permet une separation entre le traitement des données
et la façon dont elles sont affichées
• Utilisation du principe de “binding” au maximum
MVVM Light Toolkit
• Framework libre et gratuit facilitant l’implémentation du pattern
MVVM
• Crée par Laurent Bugnion (GalaSoft)
• Utilisable avec:
• WPF
• Windows 10
• Xamarin
• Silverlight
• Site officiel: http://www.galasoft.ch/mvvm/
• Téléchargeable via NuGet
Comparaison rapide entre
MVVM, MVC et MVP
Architecture
• DataService
• Classes d’accès à une ressource externe (base de données,
webservice, flux JSON, flux RSS, etc…)
• Model
• Des classes simples (POCO) représentant les données
• ViewModel
• Des fichiers .cs
• Vue
• Des fichier .xaml et .xaml.cs
Architecture
• Une Vue = un ViewModel
• Un ViewModel peut être lié à plusieurs vues (mais pas l’inverse)
• Le ViewModel est l’adaptation du modèle pour la vue. Son rôle est donc
autre que celui du Contrôleur MVC.
• Le ViewModel et la Vue sont liés en utilisant le binding
• Liaison des contrôles d’affichage (ListBox/ComboBox/TextBox…) à des
données
• Liaison des contrôles d’action (Button/Image/Slider…) à des commandes
Notes pour cette présentation
• Les exemples utilisés s’appuient sur un projet de
gestion de cave à vins réalisé avec WPF.
• Pour simplifier l’implémentation de MVVM, nous
avons utilisé le framework MVVM Light Toolkit.
Exemple de Model
public class Vin
{
public string Nom { get; set; }
public string Appellation { get; set; }
public Region Region { get; set; }
public int Annee { get; set; }
}
La classe la plus simple possible (POCO)
Exemple de ViewModel
public interface IMainViewModel
{
public string Titre { get; set; }
public ObservableCollection<Vin> Vins { get; }
public ICommand ChargerVinsCommand { get; }
}
Déclaration dans une interface
Données
Commandes
Exemple de ViewModel
public class MainViewModel : ViewModelBase, IMainViewModel
{
public MainViewModel()
{
Vins = new ObservableCollection<Vin>();
ChargerVinsCommand = new RelayCommand(ChargerVins);
}
private string _titre;
public string Titre
{
get { return _titre; }
set
{
_titre = value;
RaisePropertyChanged();
}
}
public ObservableCollection<Vin> Vins { get; private set; }
public ICommand ChargerVinsCommand { get; private set; }
private void ChargerVins()
{
WebserviceClient client = new WebServiceClient();
IList<Vin> vins = client.GetVins();
Vins.Clear();
foreach (var vin in vins)
Vins.Add(vin);
}
}
Implémentation
Données
Commandes
Initialisation
Composition du ViewModel
• Le ViewModel contient les données affichées dans la Vue
• Il permet de faire abstraction de la manière dont elles sont présentées
• On va agir directement sur les données et non plus sur les contrôles
graphiques
• Le ViewModel contient les commandes (actions métiers) de
la Vue
• Afficher ou modifier une donnée est une action métier
• Lancer une animation ou masquer un contrôle n’en est pas une
• Chaque classe ViewModel hérite de la classe
ViewModelBase, provenant de MVVM Light Toolkit
Focus : Binder une donnée
public class MainViewModel : ViewModelBase, IMainViewModel
{
private string _titre;
public string Titre
{
get { return _titre; }
set
{
_titre = value;
RaisePropertyChanged();
}
}
}
Focus : Binder une donnée
• Côté ViewModel:
• Pour une donnée, on crée un attribut privé et une propriété publique
• Dans le setter, on appelle la méthode RaisePropertyChanged. Cette méthode
permet d’avertir la Vue que la donnée a été modifiée
• RaisePropertyChanged est contenu dans la classe ObservableObject dont
ViewModelBase hérite. Cette classe implémente l’interface
INotifyPropertyChanged.
• Côté Vue:
• Veiller à ce que le mode de binding soit approprié pour le rafraîchissement
des données.
Focus : Binder une collection de données
public class MainViewModel : ViewModelBase, IMainViewModel
{
public MainViewModel()
{
Vins = new ObservableCollection<Vin>();
}
public ObservableCollection<Vin> Vins { get; private set; }
}
Focus : Binder une collection de données
• Côté ViewModel:
• On utilise le type ObservableCollection<T> (et non List<T> ou des T[])
• Cette classe implémente déjà INotifyPropertyChanged, ainsi que d’autres
interfaces pour le rafraîchissement automatique des données.
• Côté Vue:
• Veiller à ce que le mode de binding soit approprié pour le rafraîchissement
des données.
Modes de binding
• OneWay
• TwoWay
• OneTime
• OneWayToSource
• Default
La destination est mise à jour lorsque la source est mise à jour, mais pas l’inverse.
La destination est mise à jour lorsque la source est modifiée et vice-versa.
La destination prend en compte un seul changement de la source. Si la source est
de nouveau mise à jour, la destination n’est pas actualisée.
La source est mise à jour lorsque la destination est mise à jour mais pas l’inverse.
Pas toujours disponible en fonction de la technologie (ex: Windows Phone)
Utilise le comportement par défaut pour le contrôle concerné. (ex: OneWay pour
Label et TwoWay pour TextBox)
Source: donnée du ViewModel
Destination: valeur du contrôle graphique de la vue
public class MainViewModel : ViewModelBase, IMainViewModel
{
public MainViewModel()
{
ChargerVinsCommand = new RelayCommand(ChargerVins);
}
public ICommand ChargerVinsCommand { get; private set; }
private void ChargerVins()
{
Vins.Clear();
WebServiceClient client = new WebServiceClient();
foreach (Vin vin in client.GetVins())
{
Vins.Add(vin);
}
}
}
Focus : Binder une commande
• Côté ViewModel:
• Les actions métiers sont représentées par des méthodes (idéalement privées, mais il
se peut de devoir les rendre publiques pour nos tests unitaires)
• On lie ces méthodes à des commandes (objets de type ICommand)
• Le constructeur de RelayCommand prend 1 ou 2 paramètres
1. Obligatoire : La méthode qui sera appelée lors du déclenchement de la commande
2. Facultatif : La méthode qui détermine si la commande peut être exécutée ou non
• La méthode associée à la commande peut prendre un (et un seul) paramètre. On
utilise pour celà la classe RelayCommand<T>.
• Côté Vue:
• Les contrôles graphiques sont bindés aux commandes à l’aide de l’attribut Command
(et CommandParameter si un paramètre est passé)
Focus : Binder une commande
Exemple d’une View
<Page x:Class="CaveAVins.View.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="1024" Width="1280"
Title="Accueil"
DataContext="{Binding MainVM, Source={StaticResource Locator}}">
<Grid>
<TextBox Text="{Binding Titre, Mode=TwoWay}" />
<ListBox ItemsSource="{Binding Vins, Mode=OneWay}" />
<Button Command="{Binding ChargerVinsCommand}" />
</Grid>
</Page>
Info sur les commandes
• Tous les contrôles graphiques ne proposent pas d’attribut Command.
• Tous les évènements ne peuvent pas être traduits directement en
commande (ex: SelectionChanged, IsEnabled, etc…).
Heureusement, il existe deux alternatives.
• 1. Utiliser un EventTrigger dans le XAML :
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<command:EventToCommand Command="{Binding ChargerVinsCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
Info sur les commandes
private void lstVins_SelectionChanged(object sender, EventArgs e)
{
IMainViewModel vm = (IMainViewModel)DataContext;
vm.ChargerVinsCommand.Execute(null);
}
• Tous les contrôles graphiques ne proposent pas d’attribut Command.
• Tous les évènements ne peuvent pas être traduits directement en
commande (ex: SelectionChanged, IsEnabled, etc…).
Heureusement, il existe deux alternatives.
• 2. Créer un évènement et appeler la commande :
En bref sur les ViewModels…
• Le ViewModel est une adaptation du Modèle pour la Vue
• Un ViewModel comporte des données et des commandes
• Un ViewModel hérite de ViewModelBase
• ViewModelBase implémente INotifyPropertyChanged pour notifier la Vue
qu’une donnée a été modifiée
• Pour une donnée simple, on appelle RaisePropertyChanged
• Pour les collections, on utilise les ObservableCollection<T>
• Une commande peut prendre un (et un seul) paramètre.
• Si on veut faire des tests unitaires, ceux-ci peuvent être faits sur la
couche ViewModel.
ViewModelLocator
• Cette classe recense les ViewModels de notre
application
• Elle permet d’ailleurs un accès facile à nos ViewModels
• Elle permet de lier la couche Vue et ViewModel
• , et permet d’y accéder facilement.
• Elle recense également tous les Design ViewModels qui
seront utilisés par Visual Studio et Blend.
• Elle comporte également des méthodes pour décharger
les ViewModels de la mémoire vive lorsque ceux-ci ne
sont plus utilisés.
ViewModelLocator
public class ViewModelLocator
{
static ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<IMainViewModel, MainViewModel>();
}
public static IMainViewModel MainVM
{
get { return ServiceLocator.Current.GetInstance<IMainViewModel>(); }
}
public static void CleanMain()
{
SimpleIoc.Default.Unregister<IMainViewModel>();
SimpleIoc.Default.Register<IMainViewModel, MainViewModel>();
}
public static void Cleanup()
{
CleanMain();
}
}
ViewModelLocator
• On initialise le ServiceLocator dans le constructeur statique
• On référence ensuite les ViewModels de notre application à l’aide de la
classe SimpleIoC (fournie par MVVM Light Toolkit).
public class ViewModelLocator
{
static ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<IMainViewModel, MainViewModel>();
}
}
public class ViewModelLocator
{
public static IMainViewModel MainVM
{
get
{
return ServiceLocator.Current.GetInstance<IMainViewModel>();
}
}
}
ViewModelLocator
On déclare ensuite une propriété statique pour chaque ViewModel afin d’y
avoir un accès rapide depuis n’importe quelle autre classe, et notamment la
couche Vue.
Le ServiceLocator utilise des singletons. Si l’instance existe, elle est retournée
sinon elle est créée puis retournée.
Une exception est levée si le ViewModel n’a pas été enregistré au préalable
public class ViewModelLocator
{
public static void CleanMain()
{
SimpleIoc.Default.Unregister<IMainViewModel>();
SimpleIoc.Default.Register<IMainViewModel, MainViewModel>();
}
}
ViewModelLocator
Lorsqu’un ViewModel n’est plus nécessaire, il faut le retirer de la
mémoire.
On crée une méthode de nettoyage, qui va désallouer le ViewModel de
la mémoire, puis le re-préparer en cas de besoin. Il ne sera réinstancié
que si la propriété MainVM est appelée de nouveau.
public class ViewModelLocator
{
public static void Cleanup()
{
CleanMain();
}
}
ViewModelLocator
Enfin, on peut créer une méthode Cleanup qui appelle
toutes les autres méthodes Clean.
Elle peut être appelé lorsque on a besoin de réinitialiser
l’application par exemple.
Liaison couches Vue et ViewModel
• Pour lier les 2 couches, on utilise le ViewModelLocator. On le référence dans le
fichier App.xaml
• On déclare une ressource de type ViewModelLocator (nommée ici Locator)
• Exemple d’App.xaml dans un projet WPF:
<Application x:Class="CavesAVins.View.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModel="clr-namespace:CaveAVins.ViewModel;assembly=CaveAVins.ViewModel"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<viewModel:ViewModelLocator x:Key="Locator" />
</ResourceDictionary>
</Application.Resources>
</Application>
Liaison couches Vue et ViewModel
• Une fois la declaration du Locator faite, on peut aller chercher le
ViewModel de notre page.
• On lie le ViewModel à la propriété DataContext de la Vue
<Page x:Class="CaveAVins.View.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="1024" Width="1280"
Title="Accueil"
DataContext="{Binding MainVM, Source={StaticResource Locator}}">
Les Design ViewModels
• Ces classes contiennent des jeux de données fictives.
• Ces données fictives sont affichées directement dans Visual Studio et
Blend.
• Une classe Design ViewModel hérite d’un ViewModel. Pour chaque
ViewModel, on peut donc créer un Design ViewModel.
• Ainsi, il est possible de créer le rendu (les templates) de son application
avec des données fictives sans devoir lancer/debugger l’application.
Les Design ViewModels
On peut référencer nos Design ViewModels dans le ViewModelLocator
à l’aide de la propriété IsInDesignModeStatic de ViewModelBase.
Cette propriété est disponible partout et tout le temps.
public class ViewModelLocator
{
static ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (ViewModelBase.IsInDesignModeStatic)
{
// Mode Design pour Visual Studio en Blend
SimpleIoc.Default.Register<IMainViewModel, MainDesignViewModel>();
}
else
{
// Mode Debug / Run
SimpleIoc.Default.Register<IMainViewModel, MainViewModel>();
}
}
}
Les Design ViewModels
• Exemple
public class MainDesignViewModel : MainViewModel
{
public MainDesignViewModel()
{
Vins = new ObservableCollection
{
new Vin { Nom = “La Tour Carnet”,
Appellation = “Haut-Médoc”,
Region = Region.Bordeaux },
new Vin { Nom = “Merlot”,
Annee = 2011,
Region = Region.Rhone },
new Vin { Nom = “Cuvée-Silex”,
Appellation = “Pouilly-Fumé”,
Region = Region.Loire },
}
}
}
Messagerie
• La messagerie est fournie par MVVM Light Toolkit
• Elle permet d’envoyer des messages entre les classes
• Un message est un objet de n’importe quel type
• Elle permet, par exemple, d’envoyer des messages entre:
• Un ViewModel et une Vue
• Deux ViewModels
• Deux classes quelconques
• Ce mécanisme est une solution de contournement lorsqu’aucune autre
ne permet de transmettre un objet d’une classe à un autre
Messagerie
public class ExempleViewModel : ViewModelBase, IExempleViewModel
public ExempleViewModel()
{
EnvoyerPagesCommand = new RelayCommand<string>(EnvoyerMessage);
}
public Icommand ChangerPagesCommand { get; private set; }
public void EnvoyerMessage(string message)
{
MessengerInstance.Send(message);
}
}
• Côté ViewModel: Envoi du message
Messagerie
public class MainWindow
public MainWindow()
{
InitializeComponent();
Messenger.Default.Register<string>(this, ChangerPage);
}
private void AfficherMessage(string message)
{
Messenger.Show(message);
}
}
• Côté Vue: Abonnement à réception du message
Messagerie
• Pour qu’une classe reçoive un message, on utilise la méthode Register
• On utilise la méthode Unregister pour la désabonner de la messagerie
• N’importe quelle classe peut envoyer des messages, tout comme
n’importe quelle classe peut en recevoir
• Vous ne pouvez envoyer qu’un seul message à la fois, mais un message
peut être un objet de n’importe quel type
• Contrôlez-bien si votre message doit être reçu par une ou plusieurs
classes simultanément en utilisant :
• Correctement les méthodes Register et Unregister.
• Un token pour créer des canaux réservés et différencier les récepteurs
En résumé…
• MVVM = Model – View – ViewModel
• MVVM a été conçu pour faciliter la séparation entre la logique et l’affichage
• MVVM utilise la puissance du mécanisme de binding (OneWay/TwoWay)
• MVVM Light Toolkit facilite l’implémentation de MVVM dans une application
• Un ViewModel comporte des données et des commandes
• MVVM facilite les tests unitaires, puisque c’est la couche VM qui peut être testée
• Le ViewModelLocator permet l’accès facile aux ViewModels et gère leur cycle de vie
• Les Design ViewModels contiennent des données fictives qui sont directement
affichées dans Visual Studio et Blend
• La messagerie permet de transmettre des objets entre classes
Pattern MVVM avec MVVM Light Toolkit

Contenu connexe

Tendances

Workshop spring session 2 - La persistance au sein des applications Java
Workshop spring   session 2 - La persistance au sein des applications JavaWorkshop spring   session 2 - La persistance au sein des applications Java
Workshop spring session 2 - La persistance au sein des applications Java
Antoine Rey
 
Projet de fin d étude (1)
Projet de fin d étude (1)Projet de fin d étude (1)
Projet de fin d étude (1)
Sanaa Guissar
 
Soutenance PFE ingénieur génie logiciel
Soutenance PFE ingénieur génie logicielSoutenance PFE ingénieur génie logiciel
Soutenance PFE ingénieur génie logiciel
Siwar GUEMRI
 
PFE BI - INPT
PFE BI - INPTPFE BI - INPT
PFE BI - INPT
riyadadva
 
Mise en oeuvre des framework de machines et deep learning v1
Mise en oeuvre des framework de machines et deep learning v1 Mise en oeuvre des framework de machines et deep learning v1
Mise en oeuvre des framework de machines et deep learning v1
ENSET, Université Hassan II Casablanca
 
Rapport PFE : Développement D'une application de gestion des cartes de fidéli...
Rapport PFE : Développement D'une application de gestion des cartes de fidéli...Rapport PFE : Développement D'une application de gestion des cartes de fidéli...
Rapport PFE : Développement D'une application de gestion des cartes de fidéli...
Riadh K.
 

Tendances (20)

Rapport pfe 2017 Système de gestion des rendez-vous médicaux
Rapport pfe 2017 Système de gestion des rendez-vous médicaux Rapport pfe 2017 Système de gestion des rendez-vous médicaux
Rapport pfe 2017 Système de gestion des rendez-vous médicaux
 
Workshop spring session 2 - La persistance au sein des applications Java
Workshop spring   session 2 - La persistance au sein des applications JavaWorkshop spring   session 2 - La persistance au sein des applications Java
Workshop spring session 2 - La persistance au sein des applications Java
 
Projet de fin d étude (1)
Projet de fin d étude (1)Projet de fin d étude (1)
Projet de fin d étude (1)
 
Conception d’une plateforme web d’e-Commerce au sein d’une entreprise commerc...
Conception d’une plateforme web d’e-Commerce au sein d’une entreprise commerc...Conception d’une plateforme web d’e-Commerce au sein d’une entreprise commerc...
Conception d’une plateforme web d’e-Commerce au sein d’une entreprise commerc...
 
Soutenance PFE ingénieur génie logiciel
Soutenance PFE ingénieur génie logicielSoutenance PFE ingénieur génie logiciel
Soutenance PFE ingénieur génie logiciel
 
Théorie des langages - 04 Théorie des langages
Théorie des langages - 04 Théorie des langagesThéorie des langages - 04 Théorie des langages
Théorie des langages - 04 Théorie des langages
 
Pfe
PfePfe
Pfe
 
PFE BI - INPT
PFE BI - INPTPFE BI - INPT
PFE BI - INPT
 
Project Server/PowerBI : Reporting et analyse de données grâce à la Business ...
Project Server/PowerBI : Reporting et analyse de données grâce à la Business ...Project Server/PowerBI : Reporting et analyse de données grâce à la Business ...
Project Server/PowerBI : Reporting et analyse de données grâce à la Business ...
 
Mise en oeuvre des framework de machines et deep learning v1
Mise en oeuvre des framework de machines et deep learning v1 Mise en oeuvre des framework de machines et deep learning v1
Mise en oeuvre des framework de machines et deep learning v1
 
BI : Analyse des Données avec Mondrian
BI : Analyse des Données avec Mondrian BI : Analyse des Données avec Mondrian
BI : Analyse des Données avec Mondrian
 
Support JEE Spring Inversion de Controle IOC et Spring MVC
Support JEE Spring Inversion de Controle IOC et Spring MVCSupport JEE Spring Inversion de Controle IOC et Spring MVC
Support JEE Spring Inversion de Controle IOC et Spring MVC
 
TP2-UML-Correction
TP2-UML-CorrectionTP2-UML-Correction
TP2-UML-Correction
 
Support NodeJS avec TypeScript Express MongoDB
Support NodeJS avec TypeScript Express MongoDBSupport NodeJS avec TypeScript Express MongoDB
Support NodeJS avec TypeScript Express MongoDB
 
Rapport PFE : Développement D'une application de gestion des cartes de fidéli...
Rapport PFE : Développement D'une application de gestion des cartes de fidéli...Rapport PFE : Développement D'une application de gestion des cartes de fidéli...
Rapport PFE : Développement D'une application de gestion des cartes de fidéli...
 
Conception et réalisation d’une application Mobile banking
Conception et réalisation d’une application  Mobile banking  Conception et réalisation d’une application  Mobile banking
Conception et réalisation d’une application Mobile banking
 
Modélisation de données pour MongoDB
Modélisation de données pour MongoDBModélisation de données pour MongoDB
Modélisation de données pour MongoDB
 
Développement d'applications pour la plateforme Java EE
Développement d'applications pour la plateforme Java EEDéveloppement d'applications pour la plateforme Java EE
Développement d'applications pour la plateforme Java EE
 
Présentation Git & GitHub
Présentation Git & GitHubPrésentation Git & GitHub
Présentation Git & GitHub
 
Modele mvc
Modele mvcModele mvc
Modele mvc
 

En vedette

Caliburn.micro jump start composite applications for WPF, Silverlight and WP7
Caliburn.micro jump start composite applications for WPF, Silverlight and WP7Caliburn.micro jump start composite applications for WPF, Silverlight and WP7
Caliburn.micro jump start composite applications for WPF, Silverlight and WP7
Igor Moochnick
 
MVVM Light Toolkit Works Great, Less Complicated
MVVM Light ToolkitWorks Great, Less ComplicatedMVVM Light ToolkitWorks Great, Less Complicated
MVVM Light Toolkit Works Great, Less Complicated
mdc11
 
Apprendre Avec Et Par Les Nouvelles Technologies
Apprendre Avec Et Par Les Nouvelles TechnologiesApprendre Avec Et Par Les Nouvelles Technologies
Apprendre Avec Et Par Les Nouvelles Technologies
vanessa_
 
S Curit Routi Re
S Curit Routi ReS Curit Routi Re
S Curit Routi Re
guestf344b8
 

En vedette (20)

MVVM ( Model View ViewModel )
MVVM ( Model View ViewModel )MVVM ( Model View ViewModel )
MVVM ( Model View ViewModel )
 
MVVM - Model View ViewModel
MVVM - Model View ViewModelMVVM - Model View ViewModel
MVVM - Model View ViewModel
 
MVVM Lights
MVVM LightsMVVM Lights
MVVM Lights
 
Initiation à ASP.NET 4.0
Initiation à ASP.NET 4.0Initiation à ASP.NET 4.0
Initiation à ASP.NET 4.0
 
.NET Framework
.NET Framework.NET Framework
.NET Framework
 
Versioning avec Git
Versioning avec GitVersioning avec Git
Versioning avec Git
 
Langage C#
Langage C#Langage C#
Langage C#
 
Compte-rendu Agile Tour 2014 à Lille
Compte-rendu Agile Tour 2014 à LilleCompte-rendu Agile Tour 2014 à Lille
Compte-rendu Agile Tour 2014 à Lille
 
MVVM with WPF
MVVM with WPFMVVM with WPF
MVVM with WPF
 
Atelier initiation Windows Phone 7
Atelier initiation Windows Phone 7Atelier initiation Windows Phone 7
Atelier initiation Windows Phone 7
 
Design Pattern - MVC, MVP and MVVM
Design Pattern - MVC, MVP and MVVMDesign Pattern - MVC, MVP and MVVM
Design Pattern - MVC, MVP and MVVM
 
Understanding The MVVM Pattern (TechDays Belgium)
Understanding The MVVM Pattern (TechDays Belgium)Understanding The MVVM Pattern (TechDays Belgium)
Understanding The MVVM Pattern (TechDays Belgium)
 
Caliburn.micro jump start composite applications for WPF, Silverlight and WP7
Caliburn.micro jump start composite applications for WPF, Silverlight and WP7Caliburn.micro jump start composite applications for WPF, Silverlight and WP7
Caliburn.micro jump start composite applications for WPF, Silverlight and WP7
 
A Day In The Life Of A WPF/SL Integrator
A Day In The Life Of A WPF/SL IntegratorA Day In The Life Of A WPF/SL Integrator
A Day In The Life Of A WPF/SL Integrator
 
MVVM Light Toolkit Works Great, Less Complicated
MVVM Light ToolkitWorks Great, Less ComplicatedMVVM Light ToolkitWorks Great, Less Complicated
MVVM Light Toolkit Works Great, Less Complicated
 
contigo creamos deseos - Admore DC
contigo creamos deseos - Admore DCcontigo creamos deseos - Admore DC
contigo creamos deseos - Admore DC
 
Etude de cas groupe 6
Etude de cas groupe 6Etude de cas groupe 6
Etude de cas groupe 6
 
Sponsor
SponsorSponsor
Sponsor
 
Apprendre Avec Et Par Les Nouvelles Technologies
Apprendre Avec Et Par Les Nouvelles TechnologiesApprendre Avec Et Par Les Nouvelles Technologies
Apprendre Avec Et Par Les Nouvelles Technologies
 
S Curit Routi Re
S Curit Routi ReS Curit Routi Re
S Curit Routi Re
 

Similaire à Pattern MVVM avec MVVM Light Toolkit

Model view-view model (mvvm)
Model view-view model (mvvm)Model view-view model (mvvm)
Model view-view model (mvvm)
Ghassen Smida
 
ENIB cours CAI Web - Séance 4 - Frameworks/Spring - Cours
ENIB cours CAI Web - Séance 4 - Frameworks/Spring - CoursENIB cours CAI Web - Séance 4 - Frameworks/Spring - Cours
ENIB cours CAI Web - Séance 4 - Frameworks/Spring - Cours
Horacio Gonzalez
 
#J2Code2018 - Mettez du feu à vos applications avec CodeIgniter
#J2Code2018 - Mettez du feu à vos applications avec CodeIgniter#J2Code2018 - Mettez du feu à vos applications avec CodeIgniter
#J2Code2018 - Mettez du feu à vos applications avec CodeIgniter
Atsé François-Xavier KOBON
 
Cas Pratique Du Mode DéConnecté De Silverlight
Cas Pratique Du Mode DéConnecté De SilverlightCas Pratique Du Mode DéConnecté De Silverlight
Cas Pratique Du Mode DéConnecté De Silverlight
Arnaud Auroux
 
Evolutions scub foundation 3.0 = 4.0
Evolutions scub foundation 3.0 =  4.0Evolutions scub foundation 3.0 =  4.0
Evolutions scub foundation 3.0 = 4.0
adrienhautot
 
Activity
ActivityActivity
Activity
dido
 
M20246 formation-piloter-et-controler-un-cloud-prive-avec-microsoft-system-ce...
M20246 formation-piloter-et-controler-un-cloud-prive-avec-microsoft-system-ce...M20246 formation-piloter-et-controler-un-cloud-prive-avec-microsoft-system-ce...
M20246 formation-piloter-et-controler-un-cloud-prive-avec-microsoft-system-ce...
CERTyou Formation
 

Similaire à Pattern MVVM avec MVVM Light Toolkit (20)

Introducthion mvvm avec wpf
Introducthion mvvm avec wpfIntroducthion mvvm avec wpf
Introducthion mvvm avec wpf
 
Mvc (5)
Mvc (5)Mvc (5)
Mvc (5)
 
Model view-view model (mvvm)
Model view-view model (mvvm)Model view-view model (mvvm)
Model view-view model (mvvm)
 
Prezentare ASP.Net.pptx
Prezentare ASP.Net.pptxPrezentare ASP.Net.pptx
Prezentare ASP.Net.pptx
 
les style d'architecture
les style d'architecture les style d'architecture
les style d'architecture
 
ENIB cours CAI Web - Séance 4 - Frameworks/Spring - Cours
ENIB cours CAI Web - Séance 4 - Frameworks/Spring - CoursENIB cours CAI Web - Séance 4 - Frameworks/Spring - Cours
ENIB cours CAI Web - Séance 4 - Frameworks/Spring - Cours
 
Spring Ioc.pdf
Spring Ioc.pdfSpring Ioc.pdf
Spring Ioc.pdf
 
#J2Code2018 - Mettez du feu à vos applications avec CodeIgniter
#J2Code2018 - Mettez du feu à vos applications avec CodeIgniter#J2Code2018 - Mettez du feu à vos applications avec CodeIgniter
#J2Code2018 - Mettez du feu à vos applications avec CodeIgniter
 
MVVM de A à Z
MVVM de A à ZMVVM de A à Z
MVVM de A à Z
 
Java dans Windows Azure, l'exemple de JOnAS
Java dans Windows Azure, l'exemple de JOnASJava dans Windows Azure, l'exemple de JOnAS
Java dans Windows Azure, l'exemple de JOnAS
 
Cas Pratique Du Mode DéConnecté De Silverlight
Cas Pratique Du Mode DéConnecté De SilverlightCas Pratique Du Mode DéConnecté De Silverlight
Cas Pratique Du Mode DéConnecté De Silverlight
 
Gatekeeper par Guillaume Faure
Gatekeeper par Guillaume FaureGatekeeper par Guillaume Faure
Gatekeeper par Guillaume Faure
 
AngularJS
AngularJSAngularJS
AngularJS
 
Evolutions scub foundation 3.0 = 4.0
Evolutions scub foundation 3.0 =  4.0Evolutions scub foundation 3.0 =  4.0
Evolutions scub foundation 3.0 = 4.0
 
Industrialiser le développement avec silverlight 4 et wcf ria services
Industrialiser le développement avec silverlight 4 et wcf ria servicesIndustrialiser le développement avec silverlight 4 et wcf ria services
Industrialiser le développement avec silverlight 4 et wcf ria services
 
Activity
ActivityActivity
Activity
 
Perf university
Perf universityPerf university
Perf university
 
Gwt fast overview_v1
Gwt fast overview_v1Gwt fast overview_v1
Gwt fast overview_v1
 
Introduction à Symfony
Introduction à SymfonyIntroduction à Symfony
Introduction à Symfony
 
M20246 formation-piloter-et-controler-un-cloud-prive-avec-microsoft-system-ce...
M20246 formation-piloter-et-controler-un-cloud-prive-avec-microsoft-system-ce...M20246 formation-piloter-et-controler-un-cloud-prive-avec-microsoft-system-ce...
M20246 formation-piloter-et-controler-un-cloud-prive-avec-microsoft-system-ce...
 

Pattern MVVM avec MVVM Light Toolkit

  • 1. L’architecture MVVM MVVM Light Toolkit Jean-Baptiste Vigneron @jbvigneron David Bottiau @dbottiau
  • 2. Sommaire • Introduction – Présentation – MVVM Light Toolkit – Comparaison rapide entre MVVM, MVC et MVP • Notes pour cette présentation • Architecture • Les ViewModels – Données – Commandes – Modes de binding • Le ViewModelLocator • Les Design ViewModels • La Messagerie
  • 3. Présentation • MVVM est un patron de conception (design-pattern) conçu à la base pour les applications .NET • Model (Modèle) – View (Vue) – ViewModel (Vue- Modèle) • Permet une separation entre le traitement des données et la façon dont elles sont affichées • Utilisation du principe de “binding” au maximum
  • 4. MVVM Light Toolkit • Framework libre et gratuit facilitant l’implémentation du pattern MVVM • Crée par Laurent Bugnion (GalaSoft) • Utilisable avec: • WPF • Windows 10 • Xamarin • Silverlight • Site officiel: http://www.galasoft.ch/mvvm/ • Téléchargeable via NuGet
  • 6.
  • 7. Architecture • DataService • Classes d’accès à une ressource externe (base de données, webservice, flux JSON, flux RSS, etc…) • Model • Des classes simples (POCO) représentant les données • ViewModel • Des fichiers .cs • Vue • Des fichier .xaml et .xaml.cs
  • 8. Architecture • Une Vue = un ViewModel • Un ViewModel peut être lié à plusieurs vues (mais pas l’inverse) • Le ViewModel est l’adaptation du modèle pour la vue. Son rôle est donc autre que celui du Contrôleur MVC. • Le ViewModel et la Vue sont liés en utilisant le binding • Liaison des contrôles d’affichage (ListBox/ComboBox/TextBox…) à des données • Liaison des contrôles d’action (Button/Image/Slider…) à des commandes
  • 9. Notes pour cette présentation • Les exemples utilisés s’appuient sur un projet de gestion de cave à vins réalisé avec WPF. • Pour simplifier l’implémentation de MVVM, nous avons utilisé le framework MVVM Light Toolkit.
  • 10. Exemple de Model public class Vin { public string Nom { get; set; } public string Appellation { get; set; } public Region Region { get; set; } public int Annee { get; set; } } La classe la plus simple possible (POCO)
  • 11. Exemple de ViewModel public interface IMainViewModel { public string Titre { get; set; } public ObservableCollection<Vin> Vins { get; } public ICommand ChargerVinsCommand { get; } } Déclaration dans une interface Données Commandes
  • 12. Exemple de ViewModel public class MainViewModel : ViewModelBase, IMainViewModel { public MainViewModel() { Vins = new ObservableCollection<Vin>(); ChargerVinsCommand = new RelayCommand(ChargerVins); } private string _titre; public string Titre { get { return _titre; } set { _titre = value; RaisePropertyChanged(); } } public ObservableCollection<Vin> Vins { get; private set; } public ICommand ChargerVinsCommand { get; private set; } private void ChargerVins() { WebserviceClient client = new WebServiceClient(); IList<Vin> vins = client.GetVins(); Vins.Clear(); foreach (var vin in vins) Vins.Add(vin); } } Implémentation Données Commandes Initialisation
  • 13. Composition du ViewModel • Le ViewModel contient les données affichées dans la Vue • Il permet de faire abstraction de la manière dont elles sont présentées • On va agir directement sur les données et non plus sur les contrôles graphiques • Le ViewModel contient les commandes (actions métiers) de la Vue • Afficher ou modifier une donnée est une action métier • Lancer une animation ou masquer un contrôle n’en est pas une • Chaque classe ViewModel hérite de la classe ViewModelBase, provenant de MVVM Light Toolkit
  • 14. Focus : Binder une donnée public class MainViewModel : ViewModelBase, IMainViewModel { private string _titre; public string Titre { get { return _titre; } set { _titre = value; RaisePropertyChanged(); } } }
  • 15. Focus : Binder une donnée • Côté ViewModel: • Pour une donnée, on crée un attribut privé et une propriété publique • Dans le setter, on appelle la méthode RaisePropertyChanged. Cette méthode permet d’avertir la Vue que la donnée a été modifiée • RaisePropertyChanged est contenu dans la classe ObservableObject dont ViewModelBase hérite. Cette classe implémente l’interface INotifyPropertyChanged. • Côté Vue: • Veiller à ce que le mode de binding soit approprié pour le rafraîchissement des données.
  • 16. Focus : Binder une collection de données public class MainViewModel : ViewModelBase, IMainViewModel { public MainViewModel() { Vins = new ObservableCollection<Vin>(); } public ObservableCollection<Vin> Vins { get; private set; } }
  • 17. Focus : Binder une collection de données • Côté ViewModel: • On utilise le type ObservableCollection<T> (et non List<T> ou des T[]) • Cette classe implémente déjà INotifyPropertyChanged, ainsi que d’autres interfaces pour le rafraîchissement automatique des données. • Côté Vue: • Veiller à ce que le mode de binding soit approprié pour le rafraîchissement des données.
  • 18. Modes de binding • OneWay • TwoWay • OneTime • OneWayToSource • Default La destination est mise à jour lorsque la source est mise à jour, mais pas l’inverse. La destination est mise à jour lorsque la source est modifiée et vice-versa. La destination prend en compte un seul changement de la source. Si la source est de nouveau mise à jour, la destination n’est pas actualisée. La source est mise à jour lorsque la destination est mise à jour mais pas l’inverse. Pas toujours disponible en fonction de la technologie (ex: Windows Phone) Utilise le comportement par défaut pour le contrôle concerné. (ex: OneWay pour Label et TwoWay pour TextBox) Source: donnée du ViewModel Destination: valeur du contrôle graphique de la vue
  • 19. public class MainViewModel : ViewModelBase, IMainViewModel { public MainViewModel() { ChargerVinsCommand = new RelayCommand(ChargerVins); } public ICommand ChargerVinsCommand { get; private set; } private void ChargerVins() { Vins.Clear(); WebServiceClient client = new WebServiceClient(); foreach (Vin vin in client.GetVins()) { Vins.Add(vin); } } } Focus : Binder une commande
  • 20. • Côté ViewModel: • Les actions métiers sont représentées par des méthodes (idéalement privées, mais il se peut de devoir les rendre publiques pour nos tests unitaires) • On lie ces méthodes à des commandes (objets de type ICommand) • Le constructeur de RelayCommand prend 1 ou 2 paramètres 1. Obligatoire : La méthode qui sera appelée lors du déclenchement de la commande 2. Facultatif : La méthode qui détermine si la commande peut être exécutée ou non • La méthode associée à la commande peut prendre un (et un seul) paramètre. On utilise pour celà la classe RelayCommand<T>. • Côté Vue: • Les contrôles graphiques sont bindés aux commandes à l’aide de l’attribut Command (et CommandParameter si un paramètre est passé) Focus : Binder une commande
  • 21. Exemple d’une View <Page x:Class="CaveAVins.View.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="1024" Width="1280" Title="Accueil" DataContext="{Binding MainVM, Source={StaticResource Locator}}"> <Grid> <TextBox Text="{Binding Titre, Mode=TwoWay}" /> <ListBox ItemsSource="{Binding Vins, Mode=OneWay}" /> <Button Command="{Binding ChargerVinsCommand}" /> </Grid> </Page>
  • 22. Info sur les commandes • Tous les contrôles graphiques ne proposent pas d’attribut Command. • Tous les évènements ne peuvent pas être traduits directement en commande (ex: SelectionChanged, IsEnabled, etc…). Heureusement, il existe deux alternatives. • 1. Utiliser un EventTrigger dans le XAML : <i:Interaction.Triggers> <i:EventTrigger EventName="SelectionChanged"> <command:EventToCommand Command="{Binding ChargerVinsCommand}" /> </i:EventTrigger> </i:Interaction.Triggers>
  • 23. Info sur les commandes private void lstVins_SelectionChanged(object sender, EventArgs e) { IMainViewModel vm = (IMainViewModel)DataContext; vm.ChargerVinsCommand.Execute(null); } • Tous les contrôles graphiques ne proposent pas d’attribut Command. • Tous les évènements ne peuvent pas être traduits directement en commande (ex: SelectionChanged, IsEnabled, etc…). Heureusement, il existe deux alternatives. • 2. Créer un évènement et appeler la commande :
  • 24. En bref sur les ViewModels… • Le ViewModel est une adaptation du Modèle pour la Vue • Un ViewModel comporte des données et des commandes • Un ViewModel hérite de ViewModelBase • ViewModelBase implémente INotifyPropertyChanged pour notifier la Vue qu’une donnée a été modifiée • Pour une donnée simple, on appelle RaisePropertyChanged • Pour les collections, on utilise les ObservableCollection<T> • Une commande peut prendre un (et un seul) paramètre. • Si on veut faire des tests unitaires, ceux-ci peuvent être faits sur la couche ViewModel.
  • 25. ViewModelLocator • Cette classe recense les ViewModels de notre application • Elle permet d’ailleurs un accès facile à nos ViewModels • Elle permet de lier la couche Vue et ViewModel • , et permet d’y accéder facilement. • Elle recense également tous les Design ViewModels qui seront utilisés par Visual Studio et Blend. • Elle comporte également des méthodes pour décharger les ViewModels de la mémoire vive lorsque ceux-ci ne sont plus utilisés.
  • 26. ViewModelLocator public class ViewModelLocator { static ViewModelLocator() { ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); SimpleIoc.Default.Register<IMainViewModel, MainViewModel>(); } public static IMainViewModel MainVM { get { return ServiceLocator.Current.GetInstance<IMainViewModel>(); } } public static void CleanMain() { SimpleIoc.Default.Unregister<IMainViewModel>(); SimpleIoc.Default.Register<IMainViewModel, MainViewModel>(); } public static void Cleanup() { CleanMain(); } }
  • 27. ViewModelLocator • On initialise le ServiceLocator dans le constructeur statique • On référence ensuite les ViewModels de notre application à l’aide de la classe SimpleIoC (fournie par MVVM Light Toolkit). public class ViewModelLocator { static ViewModelLocator() { ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); SimpleIoc.Default.Register<IMainViewModel, MainViewModel>(); } }
  • 28. public class ViewModelLocator { public static IMainViewModel MainVM { get { return ServiceLocator.Current.GetInstance<IMainViewModel>(); } } } ViewModelLocator On déclare ensuite une propriété statique pour chaque ViewModel afin d’y avoir un accès rapide depuis n’importe quelle autre classe, et notamment la couche Vue. Le ServiceLocator utilise des singletons. Si l’instance existe, elle est retournée sinon elle est créée puis retournée. Une exception est levée si le ViewModel n’a pas été enregistré au préalable
  • 29. public class ViewModelLocator { public static void CleanMain() { SimpleIoc.Default.Unregister<IMainViewModel>(); SimpleIoc.Default.Register<IMainViewModel, MainViewModel>(); } } ViewModelLocator Lorsqu’un ViewModel n’est plus nécessaire, il faut le retirer de la mémoire. On crée une méthode de nettoyage, qui va désallouer le ViewModel de la mémoire, puis le re-préparer en cas de besoin. Il ne sera réinstancié que si la propriété MainVM est appelée de nouveau.
  • 30. public class ViewModelLocator { public static void Cleanup() { CleanMain(); } } ViewModelLocator Enfin, on peut créer une méthode Cleanup qui appelle toutes les autres méthodes Clean. Elle peut être appelé lorsque on a besoin de réinitialiser l’application par exemple.
  • 31. Liaison couches Vue et ViewModel • Pour lier les 2 couches, on utilise le ViewModelLocator. On le référence dans le fichier App.xaml • On déclare une ressource de type ViewModelLocator (nommée ici Locator) • Exemple d’App.xaml dans un projet WPF: <Application x:Class="CavesAVins.View.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:viewModel="clr-namespace:CaveAVins.ViewModel;assembly=CaveAVins.ViewModel" StartupUri="MainWindow.xaml"> <Application.Resources> <ResourceDictionary> <viewModel:ViewModelLocator x:Key="Locator" /> </ResourceDictionary> </Application.Resources> </Application>
  • 32. Liaison couches Vue et ViewModel • Une fois la declaration du Locator faite, on peut aller chercher le ViewModel de notre page. • On lie le ViewModel à la propriété DataContext de la Vue <Page x:Class="CaveAVins.View.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="1024" Width="1280" Title="Accueil" DataContext="{Binding MainVM, Source={StaticResource Locator}}">
  • 33. Les Design ViewModels • Ces classes contiennent des jeux de données fictives. • Ces données fictives sont affichées directement dans Visual Studio et Blend. • Une classe Design ViewModel hérite d’un ViewModel. Pour chaque ViewModel, on peut donc créer un Design ViewModel. • Ainsi, il est possible de créer le rendu (les templates) de son application avec des données fictives sans devoir lancer/debugger l’application.
  • 34. Les Design ViewModels On peut référencer nos Design ViewModels dans le ViewModelLocator à l’aide de la propriété IsInDesignModeStatic de ViewModelBase. Cette propriété est disponible partout et tout le temps. public class ViewModelLocator { static ViewModelLocator() { ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); if (ViewModelBase.IsInDesignModeStatic) { // Mode Design pour Visual Studio en Blend SimpleIoc.Default.Register<IMainViewModel, MainDesignViewModel>(); } else { // Mode Debug / Run SimpleIoc.Default.Register<IMainViewModel, MainViewModel>(); } } }
  • 35. Les Design ViewModels • Exemple public class MainDesignViewModel : MainViewModel { public MainDesignViewModel() { Vins = new ObservableCollection { new Vin { Nom = “La Tour Carnet”, Appellation = “Haut-Médoc”, Region = Region.Bordeaux }, new Vin { Nom = “Merlot”, Annee = 2011, Region = Region.Rhone }, new Vin { Nom = “Cuvée-Silex”, Appellation = “Pouilly-Fumé”, Region = Region.Loire }, } } }
  • 36. Messagerie • La messagerie est fournie par MVVM Light Toolkit • Elle permet d’envoyer des messages entre les classes • Un message est un objet de n’importe quel type • Elle permet, par exemple, d’envoyer des messages entre: • Un ViewModel et une Vue • Deux ViewModels • Deux classes quelconques • Ce mécanisme est une solution de contournement lorsqu’aucune autre ne permet de transmettre un objet d’une classe à un autre
  • 37. Messagerie public class ExempleViewModel : ViewModelBase, IExempleViewModel public ExempleViewModel() { EnvoyerPagesCommand = new RelayCommand<string>(EnvoyerMessage); } public Icommand ChangerPagesCommand { get; private set; } public void EnvoyerMessage(string message) { MessengerInstance.Send(message); } } • Côté ViewModel: Envoi du message
  • 38. Messagerie public class MainWindow public MainWindow() { InitializeComponent(); Messenger.Default.Register<string>(this, ChangerPage); } private void AfficherMessage(string message) { Messenger.Show(message); } } • Côté Vue: Abonnement à réception du message
  • 39. Messagerie • Pour qu’une classe reçoive un message, on utilise la méthode Register • On utilise la méthode Unregister pour la désabonner de la messagerie • N’importe quelle classe peut envoyer des messages, tout comme n’importe quelle classe peut en recevoir • Vous ne pouvez envoyer qu’un seul message à la fois, mais un message peut être un objet de n’importe quel type • Contrôlez-bien si votre message doit être reçu par une ou plusieurs classes simultanément en utilisant : • Correctement les méthodes Register et Unregister. • Un token pour créer des canaux réservés et différencier les récepteurs
  • 40. En résumé… • MVVM = Model – View – ViewModel • MVVM a été conçu pour faciliter la séparation entre la logique et l’affichage • MVVM utilise la puissance du mécanisme de binding (OneWay/TwoWay) • MVVM Light Toolkit facilite l’implémentation de MVVM dans une application • Un ViewModel comporte des données et des commandes • MVVM facilite les tests unitaires, puisque c’est la couche VM qui peut être testée • Le ViewModelLocator permet l’accès facile aux ViewModels et gère leur cycle de vie • Les Design ViewModels contiennent des données fictives qui sont directement affichées dans Visual Studio et Blend • La messagerie permet de transmettre des objets entre classes