Dane WinForms ComboBox wiązania gotcha

głosy
44

Załóżmy, że robi coś jak poniżej

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

Więc teraz mamy 2 pola kombi związani do tej tablicy i wszystko działa poprawnie. Ale po zmianie wartości jednego pola kombi, to zmiany zarówno pola kombi do jednego z nich tylko wybranym.

Teraz wiem, że tablice są zawsze przekazywane przez referencję (dowiedziałem się, że kiedy dowiedziałem C: D), ale dlaczego na ziemi pola kombi zmienić razem? Nie wierzę, że kontrola rozwijana jest modyfikowanie kolekcji w ogóle.

Jak obejść, nie byłoby to osiągnąć Funkcjonalność, który jest oczekiwany / pożądaną

ComboBox box = new ComboBox();
box.DataSource = myitems.ToArray();
Utwórz 02/08/2008 o 17:09
źródło użytkownik
W innych językach...                            


3 odpowiedzi

głosy
37

Ma to związek z tym, jak powiązania danych są tworzone w ramach dotnet, zwłaszcza BindingContext. Na wysokim poziomie oznacza to, że jeśli nie podano inaczej, każda postać i wszystkie kontrole udziału tworzą ten sam BindingContext. Podczas ustawiania DataSourcemienia, którego ComboBoxużyje BindingContextsię dostać ConcurrenyMangager, że owija listę. ConcurrenyManagerŚledzi takich rzeczach jak aktualnie wybranej pozycji na liście.

Po ustawieniu DataSourcena sekundę ComboBoxbędzie używać tych samych BindingContext(formy), które dadzą się odniesienie w takim samym ConcurrencyManagerjak powyżej, stosuje się do utworzenia powiązania danych.

Aby uzyskać bardziej szczegółowe wyjaśnienie zobaczyć BindingContext .

Odpowiedział 02/08/2008 o 18:18
źródło użytkownik

głosy
20

Lepsze obejście (w zależności od wielkości źródła danych) może być podawanie dwóch BindingSourceobiektów (nowe jako 2,00), wiążą się z tym, zbieranie i następnie wiąże się z tymi dla comboboxes.

Załączam kompletny przykład.

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);
        }
    }
}

Jeśli chcesz mylić się nawet bardziej niż próbować zawsze deklarując wiązań w konstruktorze. Które mogą spowodować w niektórych naprawdę dziwnych błędów, stąd zawsze wiążą w przypadku obciążenia.

Odpowiedział 21/08/2008 o 15:48
źródło użytkownik

głosy
2

To może być tylko literówka, ale w kodzie podałeś tylko odwoływać się do pierwszego pola kombi podczas ustawiania źródła danych:

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

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

DataSource dla box2nie jest ustawiony.

Odpowiedział 21/08/2008 o 18:12
źródło użytkownik

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more