Источник данных Listbox не работает при добавлении в ToolStripDropDown
Я весь день боролся с этой проблемой, хотя не мог найти решение. Я прошу прощения за длинный пост, я старался быть кратким и ясным.
Вот что работает: я создаю Form
и внутри его класса я создаю ListBox
динамически и установить его DataSource
к DataTable
следующее:
public partial class FrmAddress : Form
{
private ListBox listBox1 = new ListBox();
public FrmAddress()
{
this.InitializeComponent();
[...]
this.Controls.Add(listBox1);
}
[...]
private void Load_Countries()
{
this.listBox1.DataSource = dtCountries;
this.listBox1.DisplayMember = "Country";
this.listBox1.ValueMember = "Country_ID";
}
[...]
}
Это не работает: создайте пользовательский элемент управления (наследуется от ToolStripDown
), создайте новый экземпляр ToolStripControlHost(listBox1)
добавить этот экземпляр в ToolStripDown
, Установить listBox1.DataSource
к DataTable
, когда ToolStripDown
is show, список есть, но пустой (без отображения содержимого источника данных).
public class CtlDropdownPopup : ToolStripDropDown
{
ListBox controlToPop;
ToolStripControlHost controlHost;
public CtlDropdownPopup(ListBox controlToPop)
{
this.controlToPop = controlToPop;
this.controlToPop.Location = Point.Empty;
this.controlHost = new ToolStripControlHost(this.controlToPop);
[...]
this.Items.Add(this.controlHost);
}
}
public class CtlCombobox : ComboBox
{
private readonly CtlDropdownPopup suggestionDropDown;
private readonly ListBox suggestionList = new ListBox();
public CtlCombobox()
{
this.suggestionDropDown = new CtlDropdownPopup(this.suggestionList);
}
public void Source(DataTable dt, string display, string value)
{
this.suggestionDT = dt;
this.suggestionList.DataSource = dt;
this.suggestionList.DisplayMember = display;
this.suggestionList.ValueMember = value;
}
}
Обычай CtlDropdownPopup
называется как: (упрощенно)
private CtlCombobox LstCountry;
this.LstCountry.Source(dtCountries, "Country", "Country_ID");
Как я уже сказал, ToolStripDropDown
показано с listBox1
в нем, но список пуст. Любопытно, если я изменю Source()
метод для
public void Source(DataTable dt, string display, string value)
{
this.suggestionDT = dt;
// this.suggestionList.DataSource = dt;
// this.suggestionList.DisplayMember = display;
// this.suggestionList.ValueMember = value;
if (this.suggestionList != null)
{
foreach (DataRow row in dt.Rows)
{
this.suggestionList.Items.Add(row[display].ToString());
}
}
}
Список отображается с элементами на нем. Хотя этот обходной путь делает свою работу, досадно не найти ответ, почему я не могу установить DataSource
напрямую (как я и сделал в первом примере), но добавление элементов вручную.
Любые идеи действительно помогут мне хорошо выспаться сегодня вечером:)
Мысль № 1: я верю, так как dtCountries
связан с другими ComboBox1.DataSource
, это может быть проблемой, поэтому я установил this.controlToPop.DataSource = dt.Copy();
в надежде "это не так или иначе связано со списком", но проблема остается.
Примечание: я пытаюсь создать специальный комбинированный список, который предлагает элементы внутри DataTable
,
Идея из https://www.codeproject.com/Tips/789705/Create-combobox-with-search-and-suggest-list
1 ответ
Вам нужно установить BindingContext
свойство ListBox.
Когда ListBox (или любой элемент управления) добавляется в форму, он наследует его BindingContext
свойство из формы. Теперь, так как вы добавляете ListBox на другой элемент управления TopLevel с .BindingContext == null
, оно не наследует это свойство от формы, следовательно, оно не имеет BindingContext
,
Вы можете просто избежать этой проблемы, создав новый BindingContext
для ListBox:
public void Source(DataTable dt, string display, string value)
{
this.suggestionDT = dt;
this.suggestionList.BindingContext = new BindingContext(); // <<<<<<<<<<<<<
this.suggestionList.DataSource = dt;
this.suggestionList.DisplayMember = display;
this.suggestionList.ValueMember = value;
}
Вы также можете скопировать BindingContext
вместо формы (либо через CtlCombobox
управление или путем передачи его в качестве параметра).
Надеюсь, это поможет.