Valeurs d'une textbox liée à celle d'une autre

Résolu
babaOrhumette Messages postés 104 Date d'inscription mardi 14 avril 2009 Statut Membre Dernière intervention 7 avril 2019 - 6 avril 2019 à 11:47
babaOrhumette Messages postés 104 Date d'inscription mardi 14 avril 2009 Statut Membre Dernière intervention 7 avril 2019 - 7 avril 2019 à 17:16
Bonjour,
J'aimerais lier une textbox à une autre automatiquement, je tente de m'expliquer.
Mon code possède 2 textbox : textBox1 et textBox2.
J'aimerais que les valeurs (numériques) de la textBox1 varient en fonction de celles de la textbox2 et réciproquement.
Que ce soit dynamique (je ne suis pas certaines du terme).

Par exemple :
Lorsque je mets manuellement la valeur 2 à la textBox1, la textBox2 change automatiquement ces valeurs en 4.
Et lorsque j'indique 6 à valeur de la textBox2 la textBox1 donne 3.

Est-ce possible ?
Merci.

3 réponses

NHenry Messages postés 15069 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 29 mai 2023 158
6 avril 2019 à 12:12
Regardes l’événement "Change" sur les TextBox.
0
Whismeril Messages postés 18414 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 7 juin 2023 624
6 avril 2019 à 13:55
Bonjour

tu peux aussi profiter du fait que C# est pensé pour la liaison de données (binding).

Tu écris une classe "métier" dont le job est de virtualiser un objet réel, une action, un concept.
Tu bindes ensuite une instance ou une collection de cette classe sur ton formulaire.

Par exemple, un prix , c'est un prix unitaire hors taxe, un taux de TVA, un prix unitaire TTC, une quantité et un prix total, réduisons au prix hors taxe et ttc.
    public class Prix
    {
        private double taux = 0.2;

        private double ht;

        public double HT
        {
            get { return ht; }
            set
            {
                ht = value;
                TTC = ht * (1.0 + taux);
            }
        }

        private double ttc;

        public double TTC
        {
            get { return ttc; }
            set
            {
                ttc = value;
                HT = ttc / (1.0 + taux);
            }
        }

    }

Quand on saisie la propriété HT ça calcule automatiquement TTC, et quand on saisie TTC, ça calcule automatiquement HT.
Le hic, pour l'instant, c'est qu'on va rentrer dans une boucle sans fin, si tu saisie l'un ça saisie l'autre qui ressaisie l'un qui ressaisie l'autre etc...
Faut donc mettre un filet
    public class Prix
    {
        private double taux = 0.2;

        private double ht;

        public double HT
        {
            get { return ht; }
            set
            {
                if (ht != value)
                {
                    ht = value;
                    TTC = ht * (1.0 + taux);
                }
            }
        }

        private double ttc;

        public double TTC
        {
            get { return ttc; }
            set
            {
                if(ttc != value)
                {
                    ttc = value;
                    HT = ttc / (1.0 + taux);
                }
            }
        }

    }

tu saisies l'un ça saisie l'autre qui veut ressaisir le premier mais comme c'est la même valeur ça s'arrête là. On n'est pas à l'abris d'un effet de bord du à l'impression des doubles mais bon.

Maintenant le rôle de l'interface est "juste" d'afficher les données connues et de transmettre les données saisies par l'utilisateur. C'est le binding qui va faire le lien entre les objets et l'interface.
Cependant le binding a besoin d'être prévenu quand une donnée est mise à jour.
On va donc implémenter l'ineterface INotifyPropertyChanged, qui comme son non l'indique signale qu'une propriété a été modifiée.

using System.ComponentModel;
namespace exemple
{
    public class Prix : INotifyPropertyChanged
    {
        private double taux = 0.2;

        private double ht;

        public double HT
        {
            get { return ht; }
            set
            {
                if (ht != value)
                {
                    ht = value;
                    GenerePropertyChanged("HT");//demande à signaler le chanagement de valeur de HT
                    TTC = ht * (1.0 + taux);
                }
            }
        }

        private double ttc;

        public double TTC
        {
            get { return ttc; }
            set
            {
                if(ttc != value)
                {
                    ttc = value;
                    GenerePropertyChanged("TTC");
                    HT = ttc / (1.0 + taux);
                }
            }
        }

        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Génère l'évènement attendu par le binding, avec le nom de la propriété
        /// </summary>
        /// <param name="Propriete"></param>
        private void GenerePropertyChanged(string Propriete)
        {
            if (this.PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(Propriete));
        }

        #endregion
    }
}



Maintenant, supposons que tu n'as qu'un prix, et 2 textbox (ta demande quoi), tu ajoutes un objet bindingSource à ton formulaire, dans les propriétés du bindingSource tu vas lui dire qu'il travaille avec une classe Prix (selon la version de VS, il faudra peut-être générer la solution avant cette étape)



Ensuite pour chaque textbox tu vas dire à quelle propriété s'attacher



Bon là tu peux me rétorquer, ça fait beaucoup de trucs à faire pour 2 textbox.
Oui mais:
  • chacun son job, la classe Prix calcule un prix et l'interface sert d'interface,
  • si la "loi" de calcul change, tu ne vas pas trifouiller dans l'interface,
  • si un jour winform n'est plus supporté ou qu'on te demande une version 100% consol, ton code métier est réutilisable tel quel,
  • tu n'as pas géré les conversions double vers string et string vers double
  • si tu as un collection de prix tu peux attacher la collection entière à une listbox ou un datagridview, et l'instance sélectionnée vers les textbox
  • si un jour tu passes à WPF, le binding est quasi obligatoire, c'est la base de cette technologie, commencer à l'apprivoiser en Winform est un atout


Plus d'infos ici
https://codes-sources.commentcamarche.net/faq/1291-utilisation-du-binding-au-travers-de-l-objet-databindingsource


0
babaOrhumette Messages postés 104 Date d'inscription mardi 14 avril 2009 Statut Membre Dernière intervention 7 avril 2019 1
6 avril 2019 à 16:55
Ok, merci NHenry.
Avec mes 6 textbox, ça tourne en boucle et j'ai droit à un "System.StackOverflowException".
Je crois comprendre le problème mais n'arrive pas à le corriger.
        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            if (textBox1.Text =="")
            {
                textBox1.Text = "0";
            }

            int a1 = Convert.ToInt32(textBox1.Text);

            
            textBox2.Text = a1.ToString(); 
            textBox3.Text = (a1 * 20).ToString(); 
            textBox4.Text = (a1 * 10).ToString(); 
            textBox5.Text = (a1 * 20).ToString(); 
            textBox6.Text = (a1 * 30).ToString(); 
            

        }

        private void textBox2_TextChanged(object sender, EventArgs e)
        {
            if (textBox2.Text == "")
            {
                textBox2.Text = "0";
            }
            int a2 = Convert.ToInt32(textBox2.Text);

            textBox1.Text = a2.ToString(); 
            
            textBox3.Text = (a2 * 20).ToString(); 
            textBox4.Text = (a2 * 10).ToString(); 
            textBox5.Text = (a2 * 20).ToString(); 
            textBox6.Text = (a2 * 30).ToString(); 
        }

        private void textBox3_TextChanged(object sender, EventArgs e)
        {
            if (textBox3.Text == "")
            {
                textBox3.Text = "0";
            }
            int a3 = Convert.ToInt32(textBox3.Text);

            textBox1.Text = (a3 / 20).ToString(); 
            textBox2.Text = (a3 / 20).ToString(); 
            
            textBox4.Text = (a3 / 2).ToString(); 
            textBox5.Text = a3.ToString(); 
            textBox6.Text = (a3 * 3 / 2).ToString(); 
        }

        private void textBox4_TextChanged(object sender, EventArgs e)
        {
            if (textBox4.Text == "")
            {
                textBox4.Text = "0";
            }

            int a4 = Convert.ToInt32(textBox4.Text);

            textBox1.Text = (a4 / 10).ToString(); 
            textBox2.Text = (a4 / 10).ToString(); 
            textBox3.Text = (a4 * 2).ToString(); 
             
            textBox5.Text = (a4 * 2).ToString(); 
            textBox6.Text = (a4 * 3).ToString(); 
        }

        private void textBox5_TextChanged(object sender, EventArgs e)
        {
            if (textBox5.Text == "")
            {
                textBox5.Text = "0";
            }

            int a5 = Convert.ToInt32(textBox5.Text);

            textBox1.Text = (a5 / 20).ToString(); 
            textBox2.Text = (a5 / 20).ToString(); 
            textBox3.Text = a5.ToString(); 
            textBox4.Text = (a5 / 2).ToString(); 
             
            textBox6.Text = (a5 * 3 / 2).ToString(); 
        }

        private void textBox6_TextChanged(object sender, EventArgs e)
        {
            if (textBox6.Text == "")
            {
                textBox6.Text = "0";
            }

            int a6 = Convert.ToInt32(textBox6.Text);

            textBox1.Text = (a6 / 30).ToString(); 
            textBox2.Text = (a6 / 30).ToString(); 
            textBox3.Text = (a6 * 3 / 2).ToString(); 
            textBox4.Text = (a6 / 30).ToString(); 
            textBox6.Text = (a6 * 2).ToString(); 
            
        }
0
NHenry Messages postés 15069 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 29 mai 2023 158
6 avril 2019 à 17:19
if (textBox2.Text.Equals(NewValue)) return;
textBox2.Text=NewValue;

Comme ça si la valeur ne change pas, ça stoppe.
0
babaOrhumette Messages postés 104 Date d'inscription mardi 14 avril 2009 Statut Membre Dernière intervention 7 avril 2019 1
6 avril 2019 à 17:55
Merci pour cet indice, j'avais pensé à peu près à la même chose sans succès.
Je l'ai placé ici mais j'ai la même erreur.

        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            if (textBox1.Text =="")
            {
                textBox1.Text = "0";
            }

            int a1 = Convert.ToInt32(textBox1.Text);

            if (textBox2.Text.Equals(a1.ToString())) return;
            textBox2.Text = a1.ToString(); 
            textBox3.Text = (a1 * 20).ToString(); 
            textBox4.Text = (a1 * 10).ToString(); 
            textBox5.Text = (a1 * 20).ToString(); 
            textBox6.Text = (a1 * 30).ToString(); 
            

        }

        private void textBox2_TextChanged(object sender, EventArgs e)
        {
            if (textBox2.Text == "")
            {
                textBox2.Text = "0";
            }
            int a2 = Convert.ToInt32(textBox2.Text);

            textBox1.Text = a2.ToString(); 
            
            textBox3.Text = (a2 * 20).ToString(); 
            textBox4.Text = (a2 * 10).ToString(); 
            textBox5.Text = (a2 * 20).ToString(); 
            textBox6.Text = (a2 * 30).ToString(); 
        }

        private void textBox3_TextChanged(object sender, EventArgs e)
        {
            if (textBox3.Text == "")
            {
                textBox3.Text = "0";
            }
            int a3 = Convert.ToInt32(textBox3.Text);

            textBox1.Text = (a3 / 20).ToString(); 
            textBox2.Text = (a3 / 20).ToString(); 
            
            textBox4.Text = (a3 / 2).ToString(); 
            textBox5.Text = a3.ToString(); 
            textBox6.Text = (a3 * 3 / 2).ToString(); 
        }

        private void textBox4_TextChanged(object sender, EventArgs e)
        {
            if (textBox4.Text == "")
            {
                textBox4.Text = "0";
            }

            int a4 = Convert.ToInt32(textBox4.Text);

            textBox1.Text = (a4 / 10).ToString(); 
            textBox2.Text = (a4 / 10).ToString(); 
            textBox3.Text = (a4 * 2).ToString(); 
             
            textBox5.Text = (a4 * 2).ToString(); 
            textBox6.Text = (a4 * 3).ToString(); 
        }

        private void textBox5_TextChanged(object sender, EventArgs e)
        {
            if (textBox5.Text == "")
            {
                textBox5.Text = "0";
            }

            int a5 = Convert.ToInt32(textBox5.Text);

            textBox1.Text = (a5 / 20).ToString(); 
            textBox2.Text = (a5 / 20).ToString(); 
            textBox3.Text = a5.ToString(); 
            textBox4.Text = (a5 / 2).ToString(); 
             
            textBox6.Text = (a5 * 3 / 2).ToString(); 
        }

        private void textBox6_TextChanged(object sender, EventArgs e)
        {
            if (textBox6.Text == "")
            {
                textBox6.Text = "0";
            }

            int a6 = Convert.ToInt32(textBox6.Text);

            textBox1.Text = (a6 / 30).ToString(); 
            textBox2.Text = (a6 / 30).ToString(); 
            textBox3.Text = (a6 * 3 / 2).ToString(); 
            textBox4.Text = (a6 / 30).ToString(); 
            textBox6.Text = (a6 * 2).ToString(); 
            
        }




Je pense que j'ai trop travaillé dessus aujourd'hui pour y voir bien clair.
0
NHenry Messages postés 15069 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 29 mai 2023 158
6 avril 2019 à 18:22
Il faut le faire dans toutes les TextBox, sinon, ce sont les autres qui bouclent.
0
babaOrhumette Messages postés 104 Date d'inscription mardi 14 avril 2009 Statut Membre Dernière intervention 7 avril 2019 1
7 avril 2019 à 17:16
Parfait. Merci encore.
0