Вопрос

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

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

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

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

В качестве обходного пути это не приведет к достижению ожидаемой/желаемой функциональности.

ComboBox box = new ComboBox();
box.DataSource = myitems.ToArray();
Это было полезно?

Решение

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

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

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

Другие советы

Лучшим обходным решением (в зависимости от размера источника данных) является объявление двух 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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top