MVVM
De Banane Atomic
Aller à la navigationAller à la recherche
Définition
Séparation de la Vue et du Modèle afin d'améliorer:
- la maintenabilité: tout est rangé au bon endroit, on sait où trouver ce que l'on cherche
- les tests: simuler l'utilisation de l'application en manipulant le Vue-Modèle (Unit Tests + Mock)
- l'extension du code: le code est cloisonné, on peut ajouter ou remplacer des éléments (Design Time Data pour le Designer, Plugins)
Adaptation du modèle MVC à WPF.
Model | les données clientes.
|
View | les éléments visuels.
|
ViewModel | le code logique de la vue (vérification de la saisie)
|
- échanges bi-directionnels entre View et ViewModel grâce au DataBinding.
- View n'a pas accès à Model.
- la View utilise des commandes appeler des méthodes du ViewModel.
Framework
ViewModelBase
/// <summary> /// A method to wrap the INotifyPropertyChanged interface. /// </summary> public interface IViewModel : INotifyPropertyChanged { /// <summary> /// A method to wrap the call of the INotifyPropertyChanged.PropertyChanged event. /// </summary> /// <param name="propertyName">The name of the property which changed.</param> void OnPropertyChanged(string propertyName); } /// <summary> /// An implementation of a basis ViewModel with a useful method OnPropertyChanged /// to warn that a property has changed. /// </summary> public class ViewModelBase : IViewModel { /// <summary> /// A method to wrap the call of the PropertyChanged event. /// </summary> /// <param name="propertyName">The name of the property which changed.</param> public void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } /// <summary> /// Se produit lorsqu'une valeur de propriété est modifiée. /// </summary> public event PropertyChangedEventHandler PropertyChanged; } |
RelayCommand
ViewModel first
En fonction du type de vue-modèle, le DataTemplate permet de choisir la vue.
<Window.Resources> <DataTemplate DataType="{x:Type ViewModel1}"> <View1 /> </DataTemplate> <DataTemplate DataType="{x:Type ViewModel2}"> <View2 /> </DataTemplate> </Window.Resources> <!-- en fonction du type passé à CurrentViewModel (ViewModel1 ou ViewModel2) un DataTemplate (une vue) sera appliqué aux données de CurrentViewModel (respectivement View1 ou View2) --> <ContentControl Content="{Binding CurrentViewModel}"></ContentControl> |
public class MainWindowViewModel { public object CurrentViewModel { get; set; } } |
Refactoriser du code pour MVVM
- Rendre le Model Observable (INotifyPropertyChanged)
- Créer un ViewModel
- EventHandler → Command ou Behavior
- Injecter le DataService
- Injecter les ViewServices (DisplayMessage, Navigation)
- Binder View et ViewModel
- Ajouter des Design Time Data
- DesignDataService : IDataService
- Créer des Unit Tests: simuler (Mock) les services
- TestDataService : IDataService
- ViewService : IViewService