Подтвердить что ты не робот

Ускоренная привязка данных WinForms ComboBox

Предположим, вы делаете что-то вроде следующего

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

Итак, теперь у нас есть 2 поля со списком, связанные с этим массивом, и все работает отлично. Но когда вы меняете значение одного поля со списком, оно заменяет оба поля со списком, которые вы только что выбрали.

Теперь я знаю, что массивы всегда передаются по ссылке (узнал, что когда я выучил C: D), но с какой стати комбо-боксы изменились бы вместе? Я не верю, что элемент управления combo box вообще изменяет коллекцию.

Как обходной путь, разве это не достигло бы ожидаемой/желаемой функциональности

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

Ответ 1

Это связано с тем, как привязки данных настраиваются в инфраструктуре dotnet, особенно в BindingContext. На высоком уровне это означает, что если вы не указали иначе, каждая форма и все элементы управления формы будут иметь один и тот же BindingContext. Когда вы устанавливаете свойство DataSource, ComboBox будет использовать BindingContext, чтобы получить ConcurrenyMangager, который обертывает список. ConcurrenyManager отслеживает такие вещи, как текущая выбранная позиция в списке.

Когда вы установите DataSource второго ComboBox, он будет использовать тот же BindingContext (формы), который даст ссылку на тот же ConcurrencyManager, как указано выше, для настройки привязок данных.

Чтобы получить более подробное объяснение, см. BindingContext.

Ответ 2

Лучшее обходное решение (в зависимости от размера источника данных) состоит в том, чтобы объявить два объекта BindingSource (новые по состоянию на 2.00), привязать их к ним, а затем привязать их к выпадающим спискам.

Я прилагаю полный пример.

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

Если вы хотите еще больше запутать себя, попробуйте всегда объявлять привязки в конструкторе. Это может привести к некоторым действительно любопытным ошибкам, поэтому я всегда привязываюсь к событию Load.

Ответ 3

Это может быть только опечатка, но в коде, который вы указали, вы ссылаетесь только на первое поле со списком при настройке источника данных:

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

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

Источник данных для box2 не установлен.