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

Windows Presentation Foundation Discussion :

[MVVM] Pb de binding dynamique d'un bouton associé à un élément du masterViewModel


Sujet :

Windows Presentation Foundation

  1. #1
    Membre expérimenté Avatar de slim
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2002
    Messages
    938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2002
    Messages : 938
    Points : 1 337
    Points
    1 337
    Par défaut [MVVM] Pb de binding dynamique d'un bouton associé à un élément du masterViewModel
    Bonjour tout le monde,

    je travaille sur une application en WPF et j'utilise le pattern MVVM que je viens de découvrir.

    J'ai donc pris l'exemple de l'article écrit par Jérémy Alles, et je l'ai adapté à mon projet.
    J'ai une liste de fournisseurs et de produits (pour chaque fournisseur) dans le MasterViewModel. Ces listes sont des ObservableCollection.
    De plus, je déclare des ICollectionView pour chacun de mes éléments (objets) comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    this.fournisseurCollectionView = CollectionViewSource.GetDefaultView(this.fournisseurs);
                if (this.fournisseurCollectionView == null)
                    throw new NullReferenceException("fournisseurCollectionView");
     
                this.fournisseurCollectionView.CurrentChanged += new EventHandler(this.OnCollectionViewCurrentChangedFournisseur);
    J'ai également des commandes associées aux traitements que je veux réaliser. Exemple : vendre un produit. J'ai donc la commande "commandVendreProduit".
    Dans la vue, je voudrais créer dynamiquement des boutons (personnalisés), et leur associer un fournisseur. Une fois que je clique sur un fournisseur, je dois afficher sa liste de produits (en passant pas "SelectedFournisseur" qui est de type FournisseurViewModel). Seulement voila, le SelectedFournisseur comporte toujours le premier élément de mon ObservableCollection fournisseurs. De même pour les produits...
    je n'arrive pas à récupérer le frs ou le produit sur lequel je clique.

    a l'affichage des produits je fais ca :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    UniformGrid gr = (UniformGrid)this.FindName("screen");
                gr.Children.Clear();
                gr.DataContext = ms.Produits;
     
                //ObservableCollection<ProduitViewModel> colPrd = ms.Produits;
     
                FournisseurViewModel leFournisseur = ms.SelectedFournisseur;
    Note: ms est une instance de MasterViewModel

    Puis quand je clique sur un produit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    ((Bouton)sender).DataContext = ms.SelectedProduit;
     
     
                        ms.CommandVendreProduit.Execute((ProduitViewModel)((Bouton)sender).DataContext);
    Je vais bien dans la méthode VendreProduit() mais le selectedProduit est toujours le premier de la liste du MasterViewModel et pas celui sur lequel j'ai cliqué...

    Auriez-vous une idée pour régler ce problème ?

    Merci beaucoup!

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

    Informations forums :
    Inscription : Octobre 2002
    Messages : 9 161
    Points : 19 434
    Points
    19 434
    Par défaut
    Dans ta méthode OnCollectionViewCurrentChangedFournisseur, tu appelles bien la méhode permettant de lancer l'event PropertyChanged ?

  3. #3
    Membre expérimenté Avatar de slim
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2002
    Messages
    938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2002
    Messages : 938
    Points : 1 337
    Points
    1 337
    Par défaut
    Oui...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
            private void OnCollectionViewCurrentChangedFournisseur(object sender, EventArgs e)
            {
                OnPropertyChanged("SelectedFournisseur");
            }

  4. #4
    Membre averti

    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    214
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 214
    Points : 341
    Points
    341
    Par défaut
    Salut,

    Je suis l'auteur du tutoriel en question Je suis pas certain de bien avoir compris ton soucis. Quelques questions:

    • quand tu dis "quand je clique sur un produit", tu as un event sur le Click ou tu utilises une commande ? la deuxième solution me semble plus propore...
    • en utilisant une commande, tu pourrai mettre un paramètre avec, quelque chose du genre: Command={Binding CommandVendre}, CommandParameter={Binding}...
    • pour récupéré l'item courant, tu peux aussi utiliser ICollectionView.CurrentItem

    Si tu peux nous filer un projet d'exemple on pourra regarder plus en détails...

  5. #5
    Membre expérimenté Avatar de slim
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2002
    Messages
    938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2002
    Messages : 938
    Points : 1 337
    Points
    1 337
    Par défaut
    Citation Envoyé par Jérem22 Voir le message
    Je suis l'auteur du tutoriel en question
    Il est très bien fait ! merci !
    Citation Envoyé par Jérem22 Voir le message

    • quand tu dis "quand je clique sur un produit", tu as un event sur le Click ou tu utilises une commande ? la deuxième solution me semble plus propore...
    J'utilise les deux.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    private void unBouton_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
       Produit prod = new Produit();
     
       ProduitViewModel prodVM = new ProduitViewModel((ProduitViewModel)((Bouton)sender).DataContext);
     
       //ms.SelectedProduit = prodVM;
       ms.CommandVendreProduit.Execute(prodVM);
    Citation Envoyé par Jérem22 Voir le message

    • en utilisant une commande, tu pourrai mettre un paramètre avec, quelque chose du genre: Command={Binding CommandVendre}, CommandParameter={Binding}...
    Impossible parce que j'utilise le xaml pour afficher plusieurs listes (fournisseurs et produits). Je ne fais donc pas le binding dans le xaml mais dans le cs (dynamiquement).
    Citation Envoyé par Jérem22 Voir le message

    • pour récupéré l'item courant, tu peux aussi utiliser ICollectionView.CurrentItem
    Je l'utilise aussi. Si j'ai bien compris, le selectedProduit doit etre lié au currentItem de la collectionViewProduits ?

    Citation Envoyé par Jérem22 Voir le message
    Si tu peux nous filer un projet d'exemple on pourra regarder plus en détails...
    Mon projet est exactement comme le projet de ton article, a part que je fais tous les bindings en dynamqiue et non dans xaml.

    Merci !!

  6. #6
    Membre averti

    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    214
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 214
    Points : 341
    Points
    341
    Par défaut
    Je comprends pas ce que tu veux dire par "je fais tous les bindings en C#". Pourquoi tu as besoin de faire comme ça ? Idéalement, il faudrait faire le maximum de chose en XAML :p

  7. #7
    Membre expérimenté Avatar de slim
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2002
    Messages
    938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2002
    Messages : 938
    Points : 1 337
    Points
    1 337
    Par défaut
    alors, c'est une société qui nous a livré la vue. il n'y a qu'un userControl pour afficher et la liste des fournisseurs et la liste des produits. C'est pour cela que je suis obligé de lier ce userControl aux différentes listes que j'ai dans le MasterViewModel, dans la partie C#. Du coup, il n'y a aucun binding dans le xaml. J'ai essaye de le faire en c# mais ca ne fonctionne pas...

    Finalement, ma question est : Comment mettre tous les bindings en dynamique ? (SelectedProduit, ListeProduit... )

    Merci

  8. #8
    Membre averti

    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    214
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 214
    Points : 341
    Points
    341
    Par défaut
    J'ai toujours pas compris... désolé

    Même si la vue a été faite par une autre boite, pourquoi tu ne peux pas fixer le DataContext du UserControl sur ta classe VueModèle et modifier la vue pour créer les bindings ?

    Si tu veux absolument le faire en C#, ça doit être possible, tu peux regarder cette doc.

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

    Informations forums :
    Inscription : Octobre 2002
    Messages : 9 161
    Points : 19 434
    Points
    19 434
    Par défaut
    Citation Envoyé par Jérem22 Voir le message
    Même si la vue a été faite par une autre boite, pourquoi tu ne peux pas fixer le DataContext du UserControl sur ta classe VueModèle et modifier la vue pour créer les bindings ?
    En gros, dans le Loaded de ta vue, tu fais un:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this.DataContext = new TonViewModel();

  10. #10
    Membre expérimenté Avatar de slim
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2002
    Messages
    938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2002
    Messages : 938
    Points : 1 337
    Points
    1 337
    Par défaut
    Citation Envoyé par Jérem22 Voir le message
    J'ai toujours pas compris... désolé
    Ok je reprends tout doucement alors
    Dans mon modele j'ai une Collection<Fournisseur> et une Collection<Produit> que j'obtiens à partir d'un fichier XML. chaque fournisseur a une liste de produits. je retourve donc la référence de l'id fournisseur dans le produit.
    Dans le viewModel, même chose. J'ai des collections de ProduitViewModel et FournisseurViewModel.

    Dans la vue, je n'ai qu'un seul usercontrol sur lequel j'affiche, dans un premier temps la liste des fournisseurs. A cette étape, l'utilisateur ne voit que la liste des fournisseurs. Il peut en sélectionner un pour voir sa liste de produits (toujours dans le meme UserControl). Donc, si je mets le binding fournisseurs dans le monUserControl.xaml, je ne pourrais pas le mettre sur les produits ensuite. non ? donc au chargement, je lie le datacontext du grid à la liste des fournisseurs. Mais quand je sélectionne un fournisseur, il me met toujours la liste des produits du premier fournisseur de ma Collection. On dirait que le SelectedFournisseur a toujours la première valeur de la Collection<FournisseurViewModel> dans le ViewModel (vérifié pendant le débogage).

    Citation Envoyé par Jérem22 Voir le message
    et modifier la vue pour créer les bindings ?
    Justement, c'est ce que je n'ai pas su faire lors du clic sur un fournisseur par exemple. Comment lier le SelectedFournisseur (du ViewModel) au fournisseur sélectionné ? (pas dans le xaml, dans le xaml.cs)

    J'espere que tu comprends mieux... merci en tout cas

  11. #11
    Membre expérimenté Avatar de slim
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2002
    Messages
    938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2002
    Messages : 938
    Points : 1 337
    Points
    1 337
    Par défaut
    Citation Envoyé par Thomas Lebrun Voir le message
    En gros, dans le Loaded de ta vue, tu fais un:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this.DataContext = new TonViewModel();
    Tout à fait. D'ailleurs, c'est ce que je fais au chargement de la vue. Mais mon problème se situe plus au niveau du SelectedFournisseur et SelectedProduit... Ils ont toujours la première valeur (cf post ci-haut)

    Merci

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

    Informations forums :
    Inscription : Octobre 2002
    Messages : 9 161
    Points : 19 434
    Points
    19 434
    Par défaut
    Citation Envoyé par slim Voir le message
    Tout à fait. D'ailleurs, c'est ce que je fais au chargement de la vue. Mais mon problème se situe plus au niveau du SelectedFournisseur et SelectedProduit... Ils ont toujours la première valeur (cf post ci-haut)

    Merci
    Pour moi, ca ressemble au fait que lorsque le CurrentItem de ta vue est modifiée, tu ne met pas à jour la propriété correspondante pourtant, tu as répondu (suite à ma 1ère question) que c'était fait...

  13. #13
    Membre expérimenté Avatar de slim
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2002
    Messages
    938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2002
    Messages : 938
    Points : 1 337
    Points
    1 337
    Par défaut
    Dans mon xaml.cs, j'ai deux méthodes contenant une boucle (foreach). La premiere parcours le MasterView.ListeFournisseurs et affiche une liste de boutons avec le libelle des fournisseurs. Dans la boucle je mets
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    monBouton.DataContext = listeFournisseurs.Fournisseur
    A la sortie de la boucle j'ai mis :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this.DataContext = listeFournisseurs[0]
    je mets la liste des fournisseurs en datacontext, parce que si je le mets à l'interieur de la boucle, la valeur du FournisseurViewModel est changée à chaque itération. listeFournisseurs est une collection de FournisseurViewModel.

    De même pour les produits.
    Mais quand je clique sur un produit pour executer la commande commandVendreProduit, le SelectedProduit est toujours le premier produit de ma liste dans le masterViewModel.

    Par ailleurs, j'ai mis un point d'arret sur OnPropertyChanged sur le Produit, et il ne passe jamais par cette méthode...

    Merci...

Discussions similaires

  1. Réponses: 3
    Dernier message: 27/04/2009, 17h55
  2. Ajouter un contrôle dynamique contenant des boutons
    Par koukoula dans le forum ASP.NET
    Réponses: 4
    Dernier message: 09/06/2008, 11h58
  3. Réponses: 6
    Dernier message: 08/08/2006, 11h19
  4. Ajouter objet dynamiquement via un bouton
    Par maxjaco dans le forum SWT/JFace
    Réponses: 3
    Dernier message: 23/06/2006, 16h39
  5. [VB.Net] Comment créer dynamiquement un contrôle bouton ?
    Par robert.michel9 dans le forum Windows Forms
    Réponses: 1
    Dernier message: 19/01/2006, 13h49

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