IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Silverlight Discussion :

MVVM comment fermer la vue à partir du ViewModel


Sujet :

Silverlight

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    876
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 876
    Points : 491
    Points
    491
    Par défaut MVVM comment fermer la vue à partir du ViewModel
    Bonjour,

    Dans une application, j'ai une childWindow qui possède un bouton "enregistrer".
    Quand je pousse sur le bouton, j'enregistre les modifications et je vousdrais que la ChildWindow se ferme.

    Mais puisqu'un ViewModel ne connait rien de la vue qui l'utilise, comment fermer la vue à partir du viewModel ?

  2. #2
    Rédacteur
    Avatar de Thomas Lebrun
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    9 161
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 9 161
    Points : 19 434
    Points
    19 434
    Par défaut
    Avec un message envoyé depuis le VM et intercepté par la ChildWindow ?

  3. #3
    Nouveau membre du Club
    Femme Profil pro
    Analyste Programmeur
    Inscrit en
    Mai 2011
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Analyste Programmeur

    Informations forums :
    Inscription : Mai 2011
    Messages : 45
    Points : 36
    Points
    36
    Par défaut
    En effet il faut que tu utilise les Messenger. Je te donne un exemple de ce que tu peux faire.
    Dans le ViewModel que tu utilise pour ta ChildWindow tu peux faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    public enum UserInterfaceActionEnum
        {
            None,
            CloseChildWindow
        }
    Ensuite dans ta fonction qui enregistre tu renseigne ton Messenger avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Messenger.Default.Send<UserInterfaceActionEnum>(UserInterfaceActionEnum.CloseChildWindow);
    Après tu récupère ton message dans le constructeur de ChildWindow.xaml.cs avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Messenger.Default.Register<UserInterfaceActionEnum>(this, OnUserInterfaceAction);
    OnUserInterfaceAction est la méthode où tu va dire de fermer ta fenêtre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
     public void OnUserInterfaceAction(UserInterfaceActionEnum action)
    {
        if (action == UserInterfaceActionEnum.CloseChildWindow)
         {
               this.Close();
          }
    }
    Voilà, j'espère que ça peut t'aider

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    876
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 876
    Points : 491
    Points
    491
    Par défaut
    merci pour ces réponses.

    J'ai appliqué la solution de Ninine7 qui a bien détaillé la manière de l'implémenter. Toutefois, il semble que Messenger soit lié à MVVMLight et donc elle ne fonctionne pas pour moi.

    En WPF, il y a un moyen "simple" d'identifier les fenêtres ouvertes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
                //Application.Current.Windows.Cast<Window>().SingleOrDefault(x => x.IsActive).Name = "TOTO";
    mais en Silverlight, chez moi en tous cas, le Current.Windows n'est pas reconnu.

    Comme je connais le nom de ma vue, n'y a t'il pas un moyen simple de la fermer, du style "AllOpenViews("MaVue").Close" ??
    quitte à devoir passer un "handler" à l'ouverture de ma ChildWindow ?

  5. #5
    Membre éprouvé Avatar de anthyme
    Homme Profil pro
    Inscrit en
    Mars 2004
    Messages
    1 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2004
    Messages : 1 559
    Points : 1 257
    Points
    1 257
    Par défaut
    Ce qu'il faudrait c'est un PresenterService

    Tes vues viendraient s'y déclarer (en se nommant) et tu pourrais faire appel à ce service pour les fermer.

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    876
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 876
    Points : 491
    Points
    491
    Par défaut
    Citation Envoyé par anthyme Voir le message
    Ce qu'il faudrait c'est un PresenterService

    Tes vues viendraient s'y déclarer (en se nommant) et tu pourrais faire appel à ce service pour les fermer.
    L'idée me parait bonne, mais aurais-tu un exempe de comment implémenter ce service ?? je suis pas encore expert

    Sinon j'ai trouvé un post super intéressant avec le code suivant:








    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class ViewModel 
    { 
        public Action<bool> ResponseHandler { get; set; }
    }
    public partial class View : UserControl 
    {
        public void View()
        {
            var vm = new ViewModel();
            vm.ResponseHandler = result => { if (result) { Close(); } };
            LayoutRoot.DataContext = vm; 
        }
    }
    J'ai mis en place sans problème mais il doit manquer quelque chose...

    Je rajoute donc dans mon ViewModel, dans la méthode qui enregistre mes données et puis qui doit fermer la vue:
    mais ResponseHandler est toujours null...

    voici le lien vers ce post http://forums.silverlight.net/forums...93/404623.aspx

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    876
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 876
    Points : 491
    Points
    491
    Par défaut
    Deux solutions pour le prix d'une

    La première, est basée sur mon post précédent:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class ViewModel 
    { 
        public Action<bool> ResponseHandler { get; set; }
    }
    public partial class View : UserControl 
    {
        public void View()
        {
            var vm = new ViewModel();
            vm.ResponseHandler = result => { if (result) { Close(); } };
            LayoutRoot.DataContext = vm; 
        }
    }
    fonctionne avec la petite rajoute que j'avais suggérée:
    à mettre dans la méthode du viewModel qui s'exécute quand on pousse sur le bouton.

    Comme j'ai mis un événement sur la fermeture de la childWindow, je m'apperçois que je passe 2 fois dans l'événement de fermeture de ma ChildWindow. Pourquoi, je ne comprend pas.

    Deuxième piste qui elle fonctionne parfaitement,
    Dans une classe publique que j'appelle clsGlobal, je crée:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public static MonNameSpace.MesVues.MaVue gVue;
    puis dans le ViewModel de ma mainWindow, je mets:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    clsGlobal.gVue = new MaVue();
               clsGlobal.gVue.Closed += new System.EventHandler(maVue_Closed);
               clsGlobal.gVue.Show();
    Le handler n'est pas indispensable mais est un bon contrôle.
    gVue étant ma ChildWindow, dans le ViewModel de gView, il suffit de mettre sur la méthode qui est exécutée sur le click du bouton:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    clsGlobal.gVue.Close();
    Propre, ça ne lance qu'une seule fois l'événement gVue.Closed.

  8. #8
    Membre éprouvé Avatar de anthyme
    Homme Profil pro
    Inscrit en
    Mars 2004
    Messages
    1 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2004
    Messages : 1 559
    Points : 1 257
    Points
    1 257
    Par défaut
    tu créés une class "PresenterService" que tu instancie et rend singleton (tu peux la stocker sur ton objet application pour pouvoir y accéder partout).

    Et tu lui demande la creation de tes childwindow du style (je t'écris un bout de code à l'arrache) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public class PresenterService
    {
    Dictionnary<string,ChildWindow> windows = new [...];
     
    public void CreateChildWindow<T>(string name) where T : ChildWindow, new()
    {
    var child = new T();
    windows[name] = child;
    child.Show();
     
    }
     
    public void CreateChildWindow(string name)
    {
    windows[name].Close();
    windows.Remove(name);
    }
    }
    Et à la place de ton type "T" tu met ton type de vue qui hérite de childwindow.
    Apres il faudrait tester qu'une vue avec ce nom n'existe pas déjà et d'autre truc, passer des parametre contextuel, etc ... c'est juste pour que tu ais une idée.

    Sinon, il y a des framework pour gérer ça comme PRISM, NROUTE, et pas mal d'autres mais il y a souvent un "ticket d'entrée" important

  9. #9
    Membre régulier
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Novembre 2011
    Messages
    104
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Novembre 2011
    Messages : 104
    Points : 103
    Points
    103
    Par défaut
    Citation Envoyé par Golzinne Voir le message
    merci pour ces réponses.

    J'ai appliqué la solution de Ninine7 qui a bien détaillé la manière de l'implémenter. Toutefois, il semble que Messenger soit lié à MVVMLight et donc elle ne fonctionne pas pour moi.
    Pour moi qui utilise MvvmLight, la solution de Ninine7 est juste parfaite!
    Encore merci à toi!! ... avec un peu de retard ... mais ça fait tjs plaisir, non ?
    Bon code à tous!
    Frédéric

  10. #10
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2014
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Février 2014
    Messages : 1
    Points : 1
    Points
    1
    Par défaut
    Je sais que le sujet est résolu mais en utilisant l'idée de Golzinne, on peut écrire ceci à chaque instanciation d'une fenêtre à partir d'un viewmodel afin que la fenêtre ouverte se ferme pour ouvrir la nouvelle.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
                var parentWindow = Application.Current.Windows.Cast<Window>().SingleOrDefault(x => x.IsActive);
                new ChildWindow()
                {
                    DataContext = new ChildWindowViewModel()
                }.Show();
                parentWindow.Close();
    Moi ça marche parfaitement
    Bien à vous !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [MVVM] Comment fermer une Window à partir d'un ViewModel
    Par L'elfe d'Azur dans le forum Windows Presentation Foundation
    Réponses: 7
    Dernier message: 04/01/2012, 00h07
  2. comment fermer une form a partir d'une autre form?
    Par mead_Developper dans le forum Windows Forms
    Réponses: 1
    Dernier message: 26/06/2009, 20h54
  3. Réponses: 6
    Dernier message: 17/02/2009, 19h32
  4. Réponses: 6
    Dernier message: 20/12/2006, 19h22
  5. Comment fermer une fenetre a partir d'une frame
    Par ideal dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 18/08/2006, 13h39

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo