Première tentative d'implémentation du modèle MVVM sur un projet métier en ligne. Je rencontre des questions pour lesquelles je suppose qu'il existe des réponses plus simples comme celle-ci :
La fenêtre de prototype est une vue basique maître-détail d'une liste d'éléments. (une liste d'objets Personne). La vue contient un Infragistics xamDataGrid pour la liste maître. Lorsque l'élément est sélectionné dans la grille, vous pouvez modifier les détails dans le panneau inférieur et voilà, lorsque vous passez d'un champ à l'autre dans le panneau de détails, les mises à jour sont affichées en temps réel dans les données de la grille. La seule chose est que je ne veux pas de mises à jour en temps réel, je veux attendre d'appuyer sur le bouton "Appliquer les modifications".
J'espérais éviter de créer une instance séparée de la liste pour séparer la liste maître de l'ensemble de travail d'éléments que j'ajoute/supprime/modifie dans le panneau de détails.
Le chemin que j'ai emprunté :
J'ai remplacé le style de CellValuePresenter dans le champ de la grille pour pouvoir définir la liaison sur "OneWay". Cela empêche la mise à jour en temps réel.
<Setter Property="Background" Value="{Binding Path=DataItem.NameUIProperty.IsDirty, Converter={StaticResource BooleanBrushConverter}}" />
<Setter Property="IsEnabled" Value="{Binding Path=DataItem.NameUIProperty.IsEditable}" />
Ensuite, j'ajoute une commande "ApplyUpdates" (RelayCommand) à mon PersonListViewModel. Cela déclenche le message "PERSON_ITEM_UPDATED". J'utilise des ports VB des classes MVVM Foundation Messenger et RelayCommand.
#Region "Commande ApplyUpdates"
Private mApplyUpdatesCommand As New RelayCommand(AddressOf ApplyUpdates)
Public ReadOnly Property ApplyUpdatesCommand() As ICommand
Get
Return mApplyUpdatesCommand
End Get
End Property
Private Sub ApplyUpdates()
'les modifications sont déjà dans l'objet dans la liste donc nous n'avons rien à faire ici sauf envoyer le message Applied
Messages.AppMessenger.NotifyColleagues(Messages.PERSON_ITEM_UPDATED)
End Sub
#End Region
Le PersonView s'enregistre pour le message PERSON_ITEM_UPDATED et reboucle la grille lorsque le message est reçu.
'Dans l'événement Loaded
'Enregistrer pour les messages de fenêtre qui nous intéressent
Messages.AppMessenger.Register(Messages.PERSON_ITEM_UPDATED, AddressOf OnPersonItemUpdated)
'Gestionnaire d'événements
Private Sub OnPersonItemUpdated()
PersonGrid.DataSource = Nothing
PersonGrid.DataSource = mViewModel.List
End Sub
Donc, ça fonctionne, mais ça sent mauvais. La vue semble contenir trop de logique et le ViewModel ne dicte pas l'état de l'interface utilisateur, c'est la vue qui le fait.
Qu'est-ce que je rate ? Quelle méthode utiliseriez-vous pour que le ViewModel retarde la publication des modifications à la vue ?
Mise à jour : Je suis maintenant en train de créer un ViewModel personnalisé pour la grille (lecture seule, pas de notifications PropertyChanged) et un ViewModel modifiable pour la zone de détails. Les deux MV envelopperaient les mêmes objets métier, mais la version en lecture seule ne publierait pas les modifications. Cela laisserait au VM le contrôle de la mise à jour de la vue.