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

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    septembre 2017
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : septembre 2017
    Messages : 37
    Points : 23
    Points
    23

    Par défaut Communication entre 2 classes de 2 projets distincts

    Bonjour,
    J'ai une solution avec 2 projets :
    - projetA qui contient la classe CA. J'ai un ElementHost qui utilise un WPF de la classe CB
    - projetB qui contient la classe CB (un WPF).

    Lors d'event handler suite à des clics sur l'interface crée avec le WPF, je souhaite pouvoir appeler des méthodes de la classe CA à partir de la classe CB.
    Mon problème c'est que je ne peux pas référencer la classe CA dans la classe CB pour cause de référence circulaire.

    Savez vous comment je peux faire ?
    Merci !

  2. #2
    Membre expert
    Avatar de wallace1
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    octobre 2008
    Messages
    1 731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : octobre 2008
    Messages : 1 731
    Points : 3 643
    Points
    3 643
    Billets dans le blog
    6

    Par défaut

    Bonsoir,

    Si tu rencontres un problème de référence circulaire c est que la structure de ton projet n est pas cohérente c est aussi simple que ça.

    ++

  3. #3
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    septembre 2017
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : septembre 2017
    Messages : 37
    Points : 23
    Points
    23

    Par défaut

    Si tu rencontres un problème de référence circulaire c est que la structure de ton projet n est pas cohérente c est aussi simple que ça.
    Qu'est ce qui n'est pas cohérent dans ma structure ? Pour utiliser un WPF, je ne vois pas comment faire autrement
    J'ai une solution avec 2 projets :
    - projetA qui contient la classe CA. J'ai mis dans le design un ElementHost qui utilise un WPF de la classe CB
    - projetB qui contient la classe CB (un WPF).
    Sur l'interface en utilisant WPF, j'ai mis plusieurs bouton et sur évenement de clic sur ces boutons je souhaite pouvoir lancer des méthodes qui sont nécessairement dans la classe CB vu que la classe CA ne me sert que pour l'interface.
    -> Ce n'est pas cohérent ?

  4. #4
    Membre actif
    Homme Profil pro
    Analyste Programmeur
    Inscrit en
    septembre 2008
    Messages
    174
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Analyste Programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2008
    Messages : 174
    Points : 294
    Points
    294

    Par défaut

    Bonjour,

    Tu pourrais par exemple fournir à ton objet CB lors de son instanciation, une fonction Callback venant de CA.
    Comme cela, CB sait quelle fonction utiliser, sans avoir besoin de savoir à qui elle est ni où elle est.

    Bonne continuation.
    L’aléatoire n’existe pas en informatique, c’est juste un moyen de dire que l’on a pas encore compris.

  5. #5
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    septembre 2017
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : septembre 2017
    Messages : 37
    Points : 23
    Points
    23

    Par défaut

    Tu veux dire passer la méthode en paramètre via un delegate lors de l'instanciation ?

    J'ai ouvert le fichier .Designer.cs du usercontrol de ma classe CA qui contient l'ElementHost (habituellement je ne le touche pas mais je ne vois pas comment faire autrement).
    Pour commencer j'ai essayé de passer en paramètre un string avant d'essayer avec une méthode.

    J'ai changé le constructeur de ma classe CB
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
            // classe CB
            public UserControl1(string s) // ajout du string
            {
                InitializeComponent();
                //Label1.Content = s;
            }
    puis dans le .Designer.cs du usercontrol de ma classe CA
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     this.userControl11 = new WPF_UI.UserControl1("Test"); // ajout de "Test"
    mais j'ai une erreur quelques ligne plus loin, sur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this.elementHost1.Child = this.userControl11;
    qui dit The variable 'userControl11' is either undeclared or was never assigned

    Qu'est ce qui cloche dans mon code ?

  6. #6
    Membre expérimenté
    Homme Profil pro
    Développeur .Net et Delphi
    Inscrit en
    juillet 2002
    Messages
    686
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur .Net et Delphi
    Secteur : Finance

    Informations forums :
    Inscription : juillet 2002
    Messages : 686
    Points : 1 607
    Points
    1 607

    Par défaut

    Bonjour,

    Effectivement, Il ne faut pas que ta classe CB référence la classe CA. La classe CB est utilisé par CA et non le contraire ! Donc si tu veux pouvoir exécuter du code de CA à un moment "décidé" par CB, tu peux utiliser soit une callback comme l'indique Kyroon, soit utiliser des events au niveau du UserControl WPF. Ta classe CA peut alors s'abonner à ces events. Exemple simplifié :

    Coté UserControl WPF :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public event EventHandler MyEvent;
    private void RaiseEvent()
    {
        MyEvent?.Invoke(this, new EventArgs());
    }
    Coté WinForm :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    private void InitializeWpf()
    {
         WpfUserControl aWpfUserControl = (WpfUserControl)elementHost1.Child;
         aWpfUserControl.MyEvent += WpfMyEvent;
    }
     
    private void WpfMyEvent(object sender, EventArgs e)
    {
        MessageBox.Show("MyEvent de WPF");
    }

  7. #7
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    septembre 2017
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : septembre 2017
    Messages : 37
    Points : 23
    Points
    23

    Par défaut

    Je pense que les callbacks correspondront mieux à ce que je cherche que les event parce que je souhaite aussi retourner des informations vers le WPF pour le modifier.
    Par contre je n'ai pas très bien compris comment utiliser un callback.
    De ce que j'ai compris un callback c'est une méthode delegate qu'on passe en paramètre. Je me trompe ?

    Mettons que dans ma classe CA, j'ai une méthode DisplayHello. Et je fais un delegate DisplayMmessage
    Je fais un delegate:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    public void DisplayHello()
    {
      MessageBox.Show("Hello");
    }
    public delegate void DisplayMessage();
    DisplayMessage dispHello = DisplayHello;
    jusque là c'est juste ?

    Comment je fais pour passer ce delegate de ma classe A vers ma classe B (je pense que c'est la suite qui a un probleme mais je ne vois pas quoi)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
            public UserControl1(*** comment spécifier que je vais recevoir un delegate ? ***)
            {
                InitializeComponent()
            }
    puis quand j'instancie dans le Designer.cs
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this.userControl11 = new WPF_UI.UserControl1(dispHello);
    Mais dès que je passe un paramètre dans le constructeur (j'ai essayé avec un string pas un delegate que je maitrise mal) j'ai cette erreur:
    The variable 'userControl11' is either undeclared or was never assigned sur la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this.elementHost1.Child = this.userControl11;

  8. #8
    Membre actif
    Homme Profil pro
    Analyste Programmeur
    Inscrit en
    septembre 2008
    Messages
    174
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Analyste Programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2008
    Messages : 174
    Points : 294
    Points
    294

    Par défaut

    Bonjour,

    Un petit exemple vite fait qui te montrera le principe.

    Le Xaml du UserControl, rien de transcendant :
    Code xaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <UserControl x:Class="WpfApplication2.UserControl1"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
        <Grid Background="DarkCyan">
            <Button Click="Button_Click" Content="Btn Toto" Height="30" Width="80"/>
        </Grid>
    </UserControl>

    Le code behind du UserControl :
    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
    19
    20
    21
    22
    23
    24
    25
    using System.Windows;
    using System.Windows.Controls;
     
    namespace WpfApplication2
    {
        /// <summary>
        /// Logique d'interaction pour UserControl1.xaml
        /// </summary>
        public partial class UserControl1 : UserControl
        {
            public delegate void Del(string pMsg);
            public Del handler;
     
            public UserControl1(Del pDelegate)
            {
                InitializeComponent();
                handler = pDelegate;
            }
     
            private void Button_Click(object sender, RoutedEventArgs e)
            {
                handler("Toto");
            }
        }
    }
    Rien de compliqué non plus, le constructeur reçoit un délégué et initialise une variable locale avec.

    Le code de la fenêtre WinForm :
    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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    using System;
    using System.Windows.Forms;
    using System.Windows.Forms.Integration;
     
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            private ElementHost _elementHost;
     
            public Form1()
            {
                InitializeComponent();
            }
     
            private void Form1_Load(object sender, EventArgs e)
            {
                _elementHost = new ElementHost();
                _elementHost.Dock = DockStyle.Fill;
                Controls.Add(_elementHost);
     
                WpfApplication2.UserControl1 wpfUC = new WpfApplication2.UserControl1(MonMessage);
                _elementHost.Child = wpfUC;
            }
     
            private void MonMessage(string pArg)
            {
                MessageBox.Show(pArg);
            }
        }
    }
    J'initialise mon ElementHost et je lui colle mon UC Wpf que j'ai instancié en lui fournissant une méthode MonMessage.

    Alors c'est Quick and Dirty mais le principe est là, et tu peux l'adapter à ton contexte.
    Je précise que je ne fais pas de WinForm donc il y a peut être mieux a faire

    Bonne continuation.
    L’aléatoire n’existe pas en informatique, c’est juste un moyen de dire que l’on a pas encore compris.

  9. #9
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    septembre 2017
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : septembre 2017
    Messages : 37
    Points : 23
    Points
    23

    Par défaut

    Ok je vois mieux.

    Par contre j'ai toujours l'erreur que j'ai cité dans mon message précédent
    The variable 'userControl11' is either undeclared or was never assigned
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    this.userControl11 = new WPF_UI.UserControl1("hello"); 
               // idem si je passe une méthode (en adaptant le constructeur) this.userControl11 = new WPF_UI.UserControl1(dispHello) j'ai la même erreur
               ...
               this.elementHost1.Child = this.userControl11;
    Dans le code tu as mis en exemple, j'ai l'impression que tu fais la même chose
    par contre je mets ça dans le code généré directement par VSTO sur le .designer.cs

    Qu'est ce que je fais mal ?

  10. #10
    Membre expérimenté
    Homme Profil pro
    Développeur .Net et Delphi
    Inscrit en
    juillet 2002
    Messages
    686
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur .Net et Delphi
    Secteur : Finance

    Informations forums :
    Inscription : juillet 2002
    Messages : 686
    Points : 1 607
    Points
    1 607

    Par défaut

    Bonjour
    Citation Envoyé par droledenm Voir le message
    Qu'est ce que je fais mal ?
    ça :
    Citation Envoyé par droledenm Voir le message
    je mets ça dans le code généré directement par VSTO sur le .designer.cs
    Ne change pas le code généré !!! Si tu veux faire ça, comme l'indique Kyroon, il faut le faire dynamiquement dans le load de ta form.

  11. #11
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    septembre 2017
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : septembre 2017
    Messages : 37
    Points : 23
    Points
    23

    Par défaut

    OK.
    Et ça pose un problème de modifier le constructeur si on utilise un elementHost ? Parce que si je ne modifie pas le code généré, il faut que la génération soit bonne une fois changé le constructeur.

    Si je change le constructeur pour qu'il accepte un string par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
            public UserControl1(string s)
            {
                InitializeComponent();
                MessageBox.Show(s);
            }
    Après avoir fait un build sur le WPF quand je veux que l'elementHost pointe vers lui j'ai le message "An error occured trying to create an object of type "WPF_UI.UserControl1". make sure the type has a default constructor"

  12. #12
    Membre actif
    Homme Profil pro
    Analyste Programmeur
    Inscrit en
    septembre 2008
    Messages
    174
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Analyste Programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2008
    Messages : 174
    Points : 294
    Points
    294

    Par défaut

    Bonjour,

    Pour confirmer ce qu'a dit ebastien, je ne touche pas au code auto-généré, laisse le vivre sa vie.

    Je pense que la différence entre ton code et le mien, c'est que ton ElementHost est posé dans ta fenêtre alors que moi je l'ai créé par code. En soit ça ne change pas grand chose, à une exception prés. Dans les propriétés de ton composant ElementHost, il ne faut pas renseigner la propriété Child (ça doit être sur (aucun)) sinon effectivement il va te réclamer le constructeur par défaut du UserControl lors sa propre création.
    Pour faire simple, le seul endroit où j'utilise le code venant du WPF, c'est ces 2 lignes dans le Form1_Load:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    WpfApplication2.UserControl1 wpfUC = new WpfApplication2.UserControl1(MonMessage);
    _elementHost.Child = wpfUC;
    où je déclare et instancie mon UserCcontrol Wpf et l'affecte à ElementHost.

    Bonne continuation.
    L’aléatoire n’existe pas en informatique, c’est juste un moyen de dire que l’on a pas encore compris.

  13. #13
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    septembre 2017
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : septembre 2017
    Messages : 37
    Points : 23
    Points
    23

    Par défaut

    Ok, maintenant mon code marche. Merci !

    Par contre pourquoi ca ne passait pas avec le code autogénéré ?
    de ce que j'ai compris de ce que tu expliquais, le problèeme vient du child.
    mais dans ton code tu as :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    WpfApplication2.UserControl1 wpfUC = new WpfApplication2.UserControl1(MonMessage);
    _elementHost.Child = wpfUC;
    Et moi dans le code auto généré j'avais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this.elementHost1.Child = this.userControl11;
    avec this.userControl11 défini par le code autogénéré.
    Ce n'est pas équivalent ?

  14. #14
    Membre actif
    Homme Profil pro
    Analyste Programmeur
    Inscrit en
    septembre 2008
    Messages
    174
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Analyste Programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2008
    Messages : 174
    Points : 294
    Points
    294

    Par défaut

    Bonjour,

    Le code auto-généré se base sur les propriétés, que tu renseigne directement dans le composant visuel, pour se générer.
    Ce n'est pas un problème en soit, par exemple dans mon code on pourrait laisser un constructeur par défaut dans l'UC en plus de celui acceptant un délégué.
    Le truc, c'est que l'UC, dans ce cas, sera instancier deux fois dont une fois pour rien :
    Une fois lors de l’exécution du code auto-généré avec le constructeur par défaut, puis une fois par toi dans ton code avec le constructeur acceptant un délégué.

    Une autre option aurait été de ne pas passer le délégué dans le constructeur, mais de l'initialiser après construction via une propriété de l'UC, mais je ne suis pas fan de ce genre de chose, suivant le contexte, ça peut être utile, mais si je peux initialiser complétement mon objet lors de son instanciation, je le fais.

    Donc pour répondre à ta question, non ce n'est pas équivalent dans le sens le code auto-généré appellera toujours le constructeur par défaut alors que toi tu as besoin d'utiliser le constructeur acceptant un paramètre.

    Bonne continuation.

    P.S. N'oublie pas de passer le sujet en résolu si cela te conviens.
    L’aléatoire n’existe pas en informatique, c’est juste un moyen de dire que l’on a pas encore compris.

  15. #15
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    septembre 2017
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : septembre 2017
    Messages : 37
    Points : 23
    Points
    23

    Par défaut

    Merci Kyroon et ebastien !

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

Discussions similaires

  1. Réponses: 0
    Dernier message: 08/07/2013, 23h25
  2. communication entre les classes
    Par sara_qt dans le forum Qt
    Réponses: 0
    Dernier message: 11/04/2009, 21h11
  3. Communication entre une classe et un thread
    Par cs_ntd dans le forum C#
    Réponses: 2
    Dernier message: 24/10/2008, 11h49
  4. Communication entre les classes
    Par jagboys dans le forum MFC
    Réponses: 6
    Dernier message: 20/06/2006, 07h32
  5. Réponses: 3
    Dernier message: 22/11/2005, 12h12

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