Partage
  • Partager sur Facebook
  • Partager sur Twitter

Synchronisation de données entre 2 ViewModels

Architecture MVVM

    9 août 2018 à 17:15:10

    Bonjour à tous,

    Je reprends un projet en .NET (Visual Studio 2012, ancienne version que je suis obligée de garder, mon client ne souhaitant pas changer, silverlight5 et Microsoft Framework 4.5)

    J'ai un souci qui concerne l'architecture MVVM que je maîtrise partiellement.

    Je travaille sur un nouvel écran qui doit afficher un datagrid. Celui-ci est alimenté par des données qui proviennent d'une vue depuis postresql, c'est plus simple d'utiliser une vue car plusieurs tables sont concernées avec des critères spécifiques sur certains champs.

    J'ai créé ma View en xaml donc, avec le code-behind adéquat. Je travaille avec 2 ViewModels (ViewModel_1 et ViewModel_2) et leur Entity respective (description de la vue dans le 1er cas, description de la table à sauvegarder dans le second cas).

    La View que j'utilise n'affiche que les données du ViewModel_1 et tout cela fonctionne.

    L'utilisateur a la possibilité de modifier 2 attributs (une checkbox représentant un booleen, et un champ texte) dans chacune des lignes du datagrid. Les autres attributs sont en ReadOnly.

    Lorsque je souhaite sauvegarder les données modifiées dans le datagrid , je fais appel au ViewModel_2 qui lui, ne devrait contenir que les données modifiables et la clé de l'enregistrement à modifier dans la table adéquate. La construction de la requéte se fait à l'aide de l'entity.

    Est-il possible de synchroniser les données modifiées dans le datagrid (faisant référence au ViewModel_1) avec les données du ViewModel_2, de façon à pouvoir utiliser la méthode de sauvegarde du ViewModel_2 ensuite ?

    J'ai essayé plusieurs méthodes et rien n'est concluant. 

    J'ai ajouté PropertyChanged="GridColumn_PropertyChanged" au niveau des contrôles concernés dans le xaml.

    J'ai tenté CellValueChanging="mainTableView_SelectedItemChanging" dans le fichier xaml, afin de récupérer les  numéros de colonne et de ligne modifiés, afin de répercuter les modifcations dans le second viewmodel .

    Tout cela n'a pas fonctionné.

    J'ai également cherché pas mal sur les forums mais je n'ai trouvé que des cas particuliers.

    Y'a t'il une solution plus simple ? Y'a t'il une solution d'ailleurs ?

    Je fais appel à vos compétences qui m'aideront à m'améliorer dans ce domaine, en tous cas, je l'espère.

    Merci à vous.

    namespace Prevision.Entities.FlightData
    {
        [DatabaseTable(TableName = "volautresreguliers")]
        public class FlightAutresReguliers : IGenericTable
        {
            [Key]
            [DatabaseField(ColumnName = "numero_vol", Key = true)]
            public int Id { get; set; }
    
            [DatabaseField(ColumnName = "numero_ligne")]
            public string NumLigne { get; set; }
    
            [DatabaseField(ColumnName = "vol_traite")]
            public bool IsTreated { get; set; }
    
            [DatabaseField(ColumnName = "cie_vol")]
            public string Company { get; set; }
    
            [DatabaseField(ColumnName = "esc_vol")]
            public string Airport { get; set; }
    
            [DatabaseField(ColumnName = "date_vol")]
            public DateTime ScheduledDate { get; set; }
    
            [DatabaseField(ColumnName = "heure_vol")]
            public TimeSpan ScheduledHour { get; set; }
    
            [DatabaseField(ColumnName = "jop")]
            public double ScheduledDay { get; set; }
    
            [DatabaseField(ColumnName = "national")]
            public string Nationality { get; set; }
    
            [DatabaseField(ColumnName = "schengen")]
            public string Schengen { get; set; }
    
            [DatabaseField(ColumnName = "europe")]
            public string Europe { get; set; }
    
            [DatabaseField(ColumnName = "domtom")]
            public string DomTom { get; set; }
    
            [DatabaseField(ColumnName = "regulier")]
            public string Regulier { get; set; }
    
            [DatabaseField(ColumnName = "cie_trad")]
            public string CieTrad { get; set; }
    
            [DatabaseField(ColumnName = "comment_vol")]
            public string Comment { get; set; }

    Entity relative à la vue (visualisation des données)

    namespace Prevision.Entities.FlightData
    {
        [DatabaseTable(TableName = "MA_VOL", DefaultOrderField = "ID")]
        public class FlightLinkAutresReguliers : IGenericTable
        {
    
            [Key]
            [DatabaseField(ColumnName = "ID", Key = true)]
            public int Id { get; set; }
          
    
            [DatabaseField(ColumnName = "TRAITE")]
            public bool Traite { get; set; }
    
            [DatabaseField(ColumnName = "COMMENTAIRE")]
            public string Commentaire { get; set; }
          
        }

    Entity relative à la table à modifier (les attributs TRAITE et COMMENTAIRE sont les mêmes que dans ma première entity (vol_traite et comment_vol)).

    La vue fait référence entre autres à cette table en BDD qui doit être modifiée par l'utilisateur lorsqu'il coche l'attribut "Traite" et / ou saisit un commentaire.

    dxg:GridControl x:Name="mainGrid" ItemsSource="{Binding FlightsToDisplayCollection}" Grid.Row="1" Grid.Column="0" Margin="10,33,1,15" 
                                 CustomColumnSort="mainGrid_CustomColumnSort" FilterChanged="mainGrid_FilterChanged" Grid.RowSpan="3"  >

    XAML 1er gridControl

    <dxg:GridControl x:Name="slaveGrid" ItemsSource="{Binding LinkAutresReguliersListVM.FlightsLinkToDisplayCollection}" Grid.Row="1" Grid.Column="1" Margin="1,33,10,15" 
                                  Grid.RowSpan="3"  >


    XAML second gridControl

    Les deux griControl sont bindés sur des listes créées a partir des données du ViewModel, pour avoir la possibilité ensuite d'effectuer un filtrage sur un attribut quelconque.


     public FlightAutresReguliersViewModel()
            {
                if (!IsDesignMode)
                {
                    //Au lancement de la page la date de début de recherche est definie au premier janvier de l'année courante
                    // La date de fin est vide
                    From = Convert.ToDateTime("01/01/" + System.DateTime.Now.Year + " 00:00:00");
                                                                             
                    // Chargement du ViewModel principal
                    IsBusy = true;
                    LoadAll();
                    // Affectation de la liste bindée sur le grid de la View
                    this.FlightsToDisplayCollection = this.Data;
                                            
                    SubmitCompleted += new EventHandler(FlightAutresReguliersViewModel_SubmitCompleted);
                    SelectedItemChanging += new EventHandler(FlightAutresReguliersViewModel_SelectedItemChanging);
                    SelectedItemChanged += new EventHandler(FlightAutresReguliersViewModel_SelectedItemChanged);
                    
                    ApplyUserAccessibility();
    
                    // Le viewmodel récupère la demande de logout, si des données sont en cours de modification, on propose une sauvegarde
                    ((App)App.Current).PropertyChanged += GestionLogout;
    
                    this.DataLoaded += FlightAutresReguliersViewModel_DataLoaded;
                }
            }

    Constructeur du premier ViewModel

      void FlightAutresReguliersViewModel_DataLoaded(object sender, EventArgs e)
            {
                IsBusy = false;
    
                // Liste des vols non traités à partir du ViewModel.Data
                if (this.Data.Where(vol => vol.IsTreated == false).Count() > 0)
                {
                    NotTreatedFlightsCollection = this.Data.Where(vol => vol.IsTreated == false).ToList();
                }
    
    
                if (this.SelectedItem != null)
                {
                    if (this.FlightsToDisplayCollection != null && this.FlightsToDisplayCollection.Count() > 0)
                    {
                        this.SelectedItem = this.FlightsToDisplayCollection.First();
                    }
                }
    
                //On initialise le viewModel secondaire, celui qui va être sauvegardé. Il sera chargé dans le constructeur.
                LinkAutresReguliersListVM = new FlightLinksAutresReguliersViewModel();
                LinkAutresReguliersListVM.DataLoaded += FlightLinksAutresReguliersViewModel_DataLoaded;
            }

    On initialise le second ViewModel quand les données du premier sont chargées





    -
    Edité par Catherine TIMONNIER 10 août 2018 à 11:46:17

    • Partager sur Facebook
    • Partager sur Twitter

    Synchronisation de données entre 2 ViewModels

    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
    • Editeur
    • Markdown