57 votes

Liaison de données WinForms ComboBox gotcha

Ok, je suis un développeur web, mais je me retrouve à barboter dans les windows forms projets chaque maintenant et puis. Une chose qui confond moi à ce jour est la suivante.

Supposons que vous faites quelque chose comme ce qui suit

List<string> myitems = new List<string>
{
    "Item 1",
    "Item 2",
    "Item 3"
};

ComboBox box = new ComboBox();
box.DataSource = myitems;

ComboBox box2 = new ComboBox();
box2.DataSource = myitems

Alors maintenant, nous avons 2 zones de liste déroulante liée à ce tableau, et tout fonctionne bien. Mais lorsque vous modifiez la valeur d'une zone de liste déroulante, il modifie à la FOIS les zones de liste déroulante à celui que vous venez de sélectionner.

Maintenant, je sais que les Tableaux sont toujours passés par référence (appris que lorsque j'ai appris le C :D), mais pourquoi sur terre serait le combo boîtes de changement? Je ne crois pas que le contrôle zone de liste modifiable est la modification de la collection à tous.

Pour contourner ce problème, ne pas cela permettrait de réaliser la fonctionnalité attendue ou souhaitée

ComboBox box = new ComboBox();
box.DataSource = myitems.ToArray();

39voto

Robert Höglund Points 5572

Cela a à voir avec la façon dont les liaisons de données sont mis en place dans le dotnet framework, en particulier l' BindingContext. Sur un niveau élevé, cela signifie que si vous n'avez pas spécifié autrement, chaque forme et tous les contrôles du formulaire de partager le même BindingContext. Lorsque vous réglez l' DataSource de la propriété de l' ComboBox va utiliser l' BindingContext pour obtenir un ConcurrenyMangager qui encapsule la liste. L' ConcurrenyManager garde une trace de ces choses que le courant de la position sélectionnée dans la liste.

Lorsque vous définissez l' DataSource de la deuxième ComboBox il utilisera le même BindingContext (les formes) qui donnera une référence au même ConcurrencyManager comme ci-dessus utilisé pour configurer les liaisons de données.

Pour obtenir une explication plus détaillée, voir BindingContext.

22voto

Quibblesome Points 14441

Une meilleure solution de contournement (selon la taille de la source de données) consiste à déclarer deux objets BindingSource (nouveaux à partir de 2,00) lient la collection à ceux-ci, puis les lient aux zones de liste déroulante.

Je joins un exemple complet.

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
    public partial class Form1 : Form
    {
        private BindingSource source1 = new BindingSource();
        private BindingSource source2 = new BindingSource();

        public Form1()
        {
            InitializeComponent();
            Load += new EventHandler(Form1Load);
        }

        void Form1Load(object sender, EventArgs e)
        {
            List<string> myitems = new List<string>
            {
                "Item 1",
                "Item 2",
                "Item 3"
            };

            ComboBox box = new ComboBox();
            box.Bounds = new Rectangle(10, 10, 100, 50);
            source1.DataSource = myitems;
            box.DataSource = source1;

            ComboBox box2 = new ComboBox();
            box2.Bounds = new Rectangle(10, 80, 100, 50);
            source2.DataSource = myitems;
            box2.DataSource = source2;

            Controls.Add(box);
            Controls.Add(box2);
        }
    }
}
 

Si vous voulez vous embrouiller encore plus, essayez de toujours déclarer les liaisons dans le constructeur. Cela peut entraîner des bugs vraiment curieux, donc je me lie toujours dans l'événement Load.

-1voto

Cela pourrait être juste une faute de frappe, mais dans le code que vous avez fourni, vous ne faites référence à la première zone de liste déroulante que lors de la définition de la source de données:

 ComboBox box = new ComboBox();
box.DataSource = myitems;

ComboBox box2 = new ComboBox();
**box**.DataSource = myitems
 

La source de données pour box2 n'est pas définie.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X