Ускоренная привязка данных 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();
Ответы
Ответ 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
не установлен.