informer le viewmodel d'un changement dans le model

informer le viewmodel d'un changement dans le model - C#/.NET managed - Programmation

Marsh Posté le 20-08-2018 à 10:20:30    

Je suis débutant et pas très calé. J'utilise pour une petite application MVVM avec c#.  
J'ai une classe Calculs dans mon Model qui est la suivante:
 

Code :
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. namespace CompteBancaire.Model
  8. {
  9.     public class Calculs : INotifyPropertyChanged
  10.     {
  11.         public event PropertyChangedEventHandler PropertyChanged;
  12.         #region Champs
  13.         private decimal sumEntree;
  14.         private decimal sumMensualisation;
  15.         //private decimal sumCreditDepense;
  16.         //private decimal sumDebitDepense;
  17.         //private decimal sumDepense;
  18.         //private decimal sumTotal;
  19.         public string NomBase;
  20.         #endregion
  21.         #region Constructeur
  22.         public Calculs()
  23.         {
  24.             // Calcul pour les entres
  25.             //NomBase = "Gestion.mdf";
  26.             //GestionContext BddGestion = new GestionContext(NomBase); // Connexion à la base de données
  27.             //SumEntree = BddGestion.Entrees.Select(c => c.Credit).Sum(); // Addition des crédits
  28.         }
  29.         #endregion
  30.         #region Setter Getter
  31.         public decimal SumEntree
  32.         {
  33.             set
  34.             {
  35.                 if (value != sumEntree)
  36.                 {
  37.                     sumEntree = value;
  38.                     if (PropertyChanged != null)
  39.                     {
  40.                         PropertyChanged(this, new PropertyChangedEventArgs("SumEntree" ));
  41.                     }
  42.                 }
  43.             }
  44.             get
  45.             {
  46.                 return sumEntree;
  47.             }
  48.         }
  49.         public decimal SumMensualisation
  50.         {
  51.             set
  52.             {
  53.                 if (value != sumMensualisation)
  54.                 {
  55.                     sumMensualisation = value;
  56.                     if (PropertyChanged != null)
  57.                     {
  58.                         PropertyChanged(this, new PropertyChangedEventArgs("SumMensualisation" ));
  59.                     }
  60.                 }
  61.             }
  62.             get
  63.             {
  64.                 return sumMensualisation;
  65.             }
  66.         }
  67.         #endregion
  68.     }
  69. }


 
je veux pouvoir changer la valeur de SumEntree dans un ViewModel2 (VM2) et en informer un ViewModel1 (VM1).
Le passage de VM2 au Model ne pose pas de problème mais je n'arrive pas et je ne comprends pas comment passer du Model à VM1.
 
Quelqu'un pourrait il me fournir des explications et quelques lignes de code en exemple

Reply

Marsh Posté le 20-08-2018 à 10:20:30   

Reply

Marsh Posté le 20-08-2018 à 15:36:20    

les viewmodels ne communiquent pas directement entre eux.  
par contre rien n'empêche d'utiliser un bus de message et d'envoyer un message (depuis VM2) et si le VM1 écoute le message dédié il va agir en conséquence.


---------------

Reply

Marsh Posté le 20-08-2018 à 19:16:29    

Merci lordankou pour ta réponse mais peux tu m'aider un peu plus s'il te plait.  
Les messages j'ai essayé mais je ne suis pas certain d'avoir bien écrit les choses et de les avoir placées aux bons endroit car ça ne fonctionne pas...
Merci

Reply

Marsh Posté le 21-08-2018 à 08:51:46    

j'utilise mvvm light qui a un bus de message :  
https://www.nuget.org/packages/MvvmLight
 
après avec vous avez la possibilité d'utiliser des messages génériques ou des messages personnalisées.
Personnellement j'évite les messages génériques (j'aime pas la précense de chaînes de caractères) et j'utilise donc une classe.
Exemple :  

Code :
  1. class MessageNotificationUpdateChampsTaille
  2. {
  3.    public int taille { get ; private set }
  4.    MessageNotificationUpdateChampsTaille(int maTaille)
  5.    {
  6.        this.taille = maTaille;
  7.    }
  8. }


 
la classe peut être vide mais peut aussi contenir des propriétés (par exemple un champ taille)
 
du coup dans le VM2 vous faites un :  
 

Code :
  1. // envoie un message de type MessageNotificationUpdateChampsTaille sur le bus de message avec comme valeur 42
  2.    Messenger.default.send(new MessageNotificationUpdateChampsTaille(42));


 
 
et dans le VM1 dans le constructeur vous vous enregistrez à ce message :  
 

Code :
  1. public VM1()
  2. {
  3.     // on s'abonne au bus de message pour écouter le message de type MessageNotificationUpdateChampsTaille et si il arrive on lance la fonction HandleMessageNotificationUpdateChampsTaille
  4.     Messenger.default.register<MessageNotificationUpdateChampsTaille>(this, HandleMessageNotificationUpdateChampsTaille);
  5.   }
  6.   private void HandleMessageNotificationUpdateChampsTaille(MessageNotificationUpdateChampsTaille monMessage)
  7.   {
  8.       // on fait se qu'on veut ici par exemple afficher un log
  9.      console.log(MessageNotificationUpdateChampsTaille.taille);
  10.   }


 
le code c'est du pseudo-code dans le sens ou je n'ai pas vérifié les majuscules et tout ça (donc pas de copier-coller à la dure) mais le principe est là.


---------------

Reply

Marsh Posté le 21-08-2018 à 08:55:16    

Merci lordankou pour avoir passé du temps à me construire ces explications. J'essaie au plus vite et je te tiens au courant.

Reply

Marsh Posté le 21-08-2018 à 10:04:41    

Après essais ça avance et je t'en remercie. Le fonctionnement est presque bon. En effet le message revoit bien une valeur à VM1, cette valeur déclenche bien le setter de ma propriété qui me sert au binding dans la vue mais l'affichage ne change pas. Pourquoi?

Reply

Marsh Posté le 21-08-2018 à 10:09:12    

berduf a écrit :

Après essais ça avance et je t'en remercie. Le fonctionnement est presque bon. En effet le message revoit bien une valeur à VM1, cette valeur déclenche bien le setter de ma propriété qui me sert au binding dans la vue mais l'affichage ne change pas. Pourquoi?


 
a voir comment est fait le setter mais ça m'est arrivée de faire un setter sur une variable privée et non la public qui était bindée à la vue.
A vérifier qu'il y a bien un RaisePropertyChanged pour indiqué à la vue que la valeur a été modifié


---------------

Reply

Marsh Posté le 21-08-2018 à 10:17:48    

Je te donne la partie du VM1 concernée. Je pense que c'est écrit correctement sauf que je ne sais pas s'il faut écrire quelque chose dans RaisePropertyChanged:
 
public decimal TotalEntree
        {
            set
            {
                totalEntree = value;
                RaisePropertyChanged("TotalEntree" );
            }
            get
            {
                return totalEntree;
            }
        }
   
        public override void RaisePropertyChanged(string nameProperty)
        {
        }
 
S'il y a une erreur je ne vois pas.
Merci pour ton aide.

Reply

Marsh Posté le 21-08-2018 à 10:40:03    

Je crois que cela vient du fait que le UserControl commandé par VM1 n'a plus le focus. Est-ce possible? Et comment faire?

Reply

Marsh Posté le 21-08-2018 à 11:33:54    

C'est encore moi. Je viens de m'apercevoir que plus aucun des binding ne fonctionne dans mon MV1. J'étais tellement axé sur le passage des valeurs de VM2 à VM1 que je n'avais pas remarqué ce problème.
As-tu une idée par hasard?

Reply

Marsh Posté le 21-08-2018 à 11:33:54   

Reply

Marsh Posté le 21-08-2018 à 11:53:45    

si plus aucun binding ne fonctionne sur le MV1 c'est que la vue n'est plus liée au viewModel


---------------

Reply

Marsh Posté le 21-08-2018 à 12:48:23    

J'ai regardé mais apparemment pas de problème de ce côté là. Je ne comprends rien

Reply

Marsh Posté le 22-08-2018 à 16:57:11    

J'ai trouvé, j'avais fait une mauvaise utilisation de RaisePropertyChanged. Maintenant ça fonctionne. C'est super. Merci

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed