Avatar billede MikkelNielsen Nybegynder
11. oktober 2010 - 16:36 Der er 9 kommentarer og
1 løsning

Data binding med combo boxes

Hej,

jeg har et lille problem med data binding, som burde være hammersimpelt at løse, men det driller alligevel.

Min form har en ArrayList, der fungerer som data source. I mit eksempel indeholder listen strings.

Derudover har jeg 5 comboboxes, der bliver lavet programmatisk. Hver af de 5 comboboxes skal "kigge på" de samme data, dvs. jeg gør noget i stil med:

for( int i = 0; i < 5; i++ )
{
    ComboBox cb = new ComboBox();
    cb.DataSource = myDataSource; // ArrayList of strings
    // Tilføj boxen til et panel eller lign.
}

Det virker også næsten. Hver combobox giver brugeren de samme valgmuligheder. Hvis indeholdet af myDataSource ændrer sig, reflekteres det i comboboxes. Fint nok... MEN, når man vælger en værdi i én combobox, så ændrer de resterende comboboxes sig også, så de peger på det samme. Med andre ord lader det til, at SelectedIndex for dem alle altid er i sync, og det var ikke meningen.

Hvad gør man så? Jeg har forsøgt følgende:

for( int i = 0; i < 5; i++ )
{
    ComboBox cb = new ComboBox();
    cb.BindingContext = new BindingContext(); // Test
    cb.DataSource = myDataSource; // ArrayList of strings
    // Tilføj boxen til et panel eller lign.
}

Nu kan jeg godt vælge noget i én combobox uden at det påvirker de andre. Desværre bliver ingen af dem opdateret, hvis indholdet af myDataSource ændrer sig, og det skulle de gerne.

Jeg har et par idéer til, hvordan jeg måske kan fuske mig ud af det, men jeg vil meget gerne høre fra nogen, der har en elegant løsning. :)

Tak på forhånd.
Avatar billede Syska Mester
11. oktober 2010 - 17:18 #1
Jeg vil næsten mene ... uden at vide om det er sådan man gør, at du bliver nød til at oprette en kopi af listen ( så længe den er lille er det ikke et så stort problem ) ...

Men synes ikke det er en elegant løsning, så mon ikke der er nogen der har en bedre løsning :-)

mvh
Avatar billede Syska Mester
11. oktober 2010 - 17:20 #2
Har ikke læst det hele ... men prøv at kigge på
http://stackoverflow.com/questions/482/winforms-combobox-data-binding-gotcha
Avatar billede lasserasch Juniormester
11. oktober 2010 - 19:32 #3
Det virker hvis du tilføjer .ToArray() på din arrayliste.

Her et eksempel.

Mvh.
Lasse



public partial class Form1 : Form
    {
        ArrayList list = new ArrayList();
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            for (int i = 0; i < 5; i++)
            {
                ComboBox c = new ComboBox();
                flowLayoutPanel1.Controls.Add(c);
            }

            BindDataSources(string.Empty);
        }

        private void BindDataSources(string text)
        {
            list.Clear();
            list.Add("appelsiner");
            list.Add("bananer");
            list.Add("citroner");

            if (text.Trim() != string.Empty)
                list.Add(text);

            foreach (Control ctrl in flowLayoutPanel1.Controls)
            {
                ComboBox c = (ComboBox)ctrl;
                c.DataSource = list.ToArray();
            }

        }
        private void button1_Click(object sender, EventArgs e)
        {
            list.Add(textBox1.Text);
            BindDataSources(textBox1.Text); 
        }
    }
Avatar billede Syska Mester
11. oktober 2010 - 19:44 #4
Ja, da ToArray() også opretter en kopi, men det kan næste ikke passe det er den mest elegante løsning som jeg også skrev i mit første indlæg.
Avatar billede lasserasch Juniormester
11. oktober 2010 - 20:02 #5
Buzzzz --> : ".ToArray()" er da en pæn nok løsning, mht. mængden af kode som er nødvendig :-)

Men forstår godt dit agument mht. performance ved store objekter. Tror så bare ikke det er så store lister man normalt binder til comboboxes...

Men løsningen er enten det eller at sætte en ny BindingContext.
Problemet er jo at de har samme BindingContext hvis man ikke definerer andet, fordi de arver det fra kontrollen de er oprettet i.

En anden ting er så at uanset om de har samme BindingContext eller ej, så opdateres inholdet af de combo bokse altså ikke bare fordi man tilføjer noget til datasourcen, når du bruger en ArrayList. Det er fordi ArrayList ikke implementer IBindingList.

Så du er nødt til at sætte datasourcen for dine comboboxes når datasourcen ændres.

Mvh.
Lasse
Avatar billede Syska Mester
11. oktober 2010 - 20:13 #6
Nej, nok mere tænkt performance problem. Hvis det endelig er objecter som er reference types, så er det jo kun referencen der kopieres over i den nye liste.

Så det med en kopi er nok ... som du er inde på den nemme løsning, og perf er nok heller ikke et problem.
Avatar billede lasserasch Juniormester
11. oktober 2010 - 20:20 #7
Men en helt anden løsning kunne være netop at bruge en datasource som implementerer iBindingList.

Så kunne en løsning se sådan ud:


public partial class Form1 : Form
    {
        BindingList<string> list = new BindingList<string>();
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            list.Clear();
            list.Add("appelsiner");
            list.Add("bananer");
            list.Add("citroner");
            for (int i = 0; i < 5; i++)
            {
                ComboBox c = new ComboBox();
                c.BindingContext = new System.Windows.Forms.BindingContext();
                c.DataSource = list;
                flowLayoutPanel1.Controls.Add(c);
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            list.Add(textBox1.Text);
        }
    }

Avatar billede MikkelNielsen Nybegynder
14. oktober 2010 - 16:43 #8
Tak til jer begge for input. I har begge nogle interessante idéer, men det er nok lasserasch's, der med sine kodeeksempler har bidraget mest mht. at bringe mig tættere på en brugbar løsning. Hvis du smider et svar, skal jeg nok acceptere det.
Avatar billede lasserasch Juniormester
14. oktober 2010 - 17:49 #9
k
Avatar billede Syska Mester
14. oktober 2010 - 18:25 #10
Nu koder jeg for det meste aldrig eksempler for folk, men kaster dem kun i den rigtige retning :-)

Det synes jeg man lærer mest af, hvis man så sidder 100% fast, så kan et eksempel altid være rart :-)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester