Привязка данных WinForms ComboBox - PullRequest
47 голосов
/ 02 августа 2008

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

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

Ответы [ 2 ]

37 голосов
/ 02 августа 2008

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

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

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

20 голосов
/ 21 августа 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...