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] Problème de binding, UserControl vers ViewModel


Sujet :

Windows Presentation Foundation

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Futur Membre du Club
    Inscrit en
    Août 2006
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 4
    Par défaut [MVVM] Problème de binding, UserControl vers ViewModel
    Bonjour

    Je développe une application graphique (MVVM), celle-ci charge un user control (non MVVM) permettant de cropper une image. L'appli principale contient un ViewModel, auquel est néanmoins attaché mon UserControl.

    Le ViewModel fournit une image (BitmapSource), le UserControl affiche cette image sans problème grace à la magie du Binding.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <Image Source="{Binding monBitmapSource}"/>
    Le cropping de l'image est géré en local, au sein de mon UserControl. Je manipule des adorners, des thumbs, et au final j'obtiens un objet PointCollection qui contient des coordonnées de points.

    Problématique:
    Je dois communiquer les nouvelles coordonnées à mon ViewModel, car celui-ci en a besoin avant de me fournir l'image suivante. Mais je ne vois pas trop comment faire dans ce sens.

    Mon ViewModel expose une propriété de type PointCollection. Comment puis je la mettre à jour ?
    Par Binding ? Oui mais comment ? Mon objet PointCollection est une variable locale au code-behind de mon UserControl, comment la relier à mon ViewModel ?
    Par l'envoi d'une commande et d'un CommandParameter ? Est-ce possible de transférer un PointCollection de cette manière ?

    Merci d'avance pour votre aide.

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

    Informations forums :
    Inscription : Octobre 2002
    Messages : 9 161
    Par défaut
    Le DataContext de ton UserControl, c'est ton ViewModel donc dans le code behind de ton UserControl, tu peux accéder au DataContext, le caster en ton VM et accéder à ses propriétés:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    var dc = this.DataContext as tonVm;
    if(dc != null)
    {
        dc.MaPointCollection = new PointCollection(...);
    }

  3. #3
    Futur Membre du Club
    Inscrit en
    Août 2006
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 4
    Par défaut
    Merci pour ta réponse.

    J'avais pensé à cette solution, mais je ne peux pas l'appliquer car mon UserControl est dans un projet à part de l'appli principale et ne connaît pas le type de mon ViewModel

    Mon UserControl doit être un composant générique (donc utilisable pour d'autres projets) et ne doit donc avoir aucune référence en dur vers l'appli principale.
    Don mon cas, c'est donc l'appli principale qui se charge de binder le DataContext du UserControl avec son ViewModel. Seule l'appli principale connaît la relation entre les deux.

    Dans le XAML de mon appli principale, j'ai donc:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    <uc:monUserControl DataContext="{Binding MonViewModel}" x:Name="monUserControl"  />
    "MonViewModel" est une propriété de type ViewModel et qui est instanciée au moment où je charge mon UserControl.

    Bref, tout ça pour dire que mon UserControl ne peut pas typer son DataContext...

  4. #4
    Membre Expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Par défaut
    Tu peux sans doute utiliser un évènement : quand le UserControl a fini sa tâche il notifie l'extérieur, ici ton application principale, en passant comme arguments la collection de points.

    Une variation est d'utiliser une ICommand comme propriété de dépendance du UserControl et de la binder à une commande de l'application principale, en passant toujours en paramètre la liste de points.

    Ainsi tu as un découplage fort entre le UserControl et le reste de l'application.

  5. #5
    Futur Membre du Club
    Inscrit en
    Août 2006
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 4
    Par défaut
    Et c'est là qu'on me perd...

    Mon ViewModel expose bien une commande qui prend un PointCollection en paramètre.

    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
     
            private RelayCommand m_cmdUpdateCoord;
            public ICommand UpdateCoord
            {
                get
                {
                  if (m_cmdUpdateCoord== null)
                  {
                      m_cmdUpdateCoord= new RelayCommand(param => UpdateCoord((PointCollection)param));
                  }
                  return m_cmdUpdateCoord;
                }
            }
     
            private void UpdateCoord(PointCollection p_newCoord)
            {
                //Je récupère les coordonnées dans mon ViewModel
            }
    Et dans le code-behind de mon UserControl, j'ai un événement CropChanged qui est levé au moment où j'ai de nouvelles coordonnées. C'est dans cet événement que je dois invoquer la commande de mon ViewModel.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
            private void CropChanged(Object sender, RoutedEventArgs rea)
            {
                PointCollection pc = GetNewCoord();
                //C'est là qu'on me perd
            }
    Comment fait-on pour déclarer la propriété de dépendance et la binder à la commande UpdateCoord de mon ViewModel ?
    J'ai parcouru plusieurs tutoriaux mais je n'ai pas trouvé d'exemple simple

  6. #6
    Membre Expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Par défaut
    Deux solutions :
    Soit exposer un évènement de plus haut-niveau accessible depuis l'extérieur du UserControl :
    Et dans le code-behind de mon UserControl, j'ai un événement CropChanged qui est levé au moment où j'ai de nouvelles coordonnées.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    public event EventHandler<CoordinatesChangedEventArgs> CoordinatesChanged;
    ...
    private void CropChanged(Object sender, RoutedEventArgs rea)
    {
        PointCollection pc = GetNewCoord();
     
        if (this.CoordinatesChanged != null)
        {
            this.CoordinatesChanged(this, new CoordinatesChangedEventArgs(...));
        }
    }
    Ou bien via une ICommand :
    Comment fait-on pour déclarer la propriété de dépendance et la binder à la commande UpdateCoord de mon ViewModel ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    private static readonly DependencyProperty CommandProperty =
        DependencyProperty.Register("Command", typeof(ICommand), typeof(LeUserControl), null);
     
    public ICommand Command
    {
        get { return this.GetValue(CommandProperty) as ICommand; }
        set { this.SetValue(CommandProperty, value); }
    }
    Et de l'extérieur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    <local:LeUserControl ... Command="{Binding UpdateCoord}" />
    Pas testé mais le principe est là.

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

Discussions similaires

  1. MVVM Problème de binding avec une class Business
    Par Oberown dans le forum Windows Presentation Foundation
    Réponses: 7
    Dernier message: 15/02/2012, 10h12
  2. Problème de Binding entre les UserControls
    Par sou_dj dans le forum Windows Presentation Foundation
    Réponses: 5
    Dernier message: 09/06/2011, 16h20
  3. Problème de binding de DataContext d'un ContextMenu en MVVM
    Par Hass_NB dans le forum Windows Presentation Foundation
    Réponses: 3
    Dernier message: 20/01/2011, 10h48
  4. Problème de Binding avec un UserControl
    Par birdyz dans le forum Windows Presentation Foundation
    Réponses: 1
    Dernier message: 20/02/2009, 12h31
  5. [WPF] Probléme de binding dans un UserControl :(
    Par UNi[FR] dans le forum Windows Presentation Foundation
    Réponses: 6
    Dernier message: 17/07/2008, 15h51

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