I have been struggling all day with this problem, although I couldn't find a solution. I apologize for the long post, I tried to be concise and clear.
This is what works: I create a Form
and inside its class I create a ListBox
dynamically and set its DataSource
to a DataTable
as follows:
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";
}
[...]
}
This does not work: Create a custom control (inherited from ToolStripDown
), create a new instance of ToolStripControlHost(listBox1)
, add that instance to the ToolStripDown
. Set the listBox1.DataSource
to a DataTable
. When ToolStripDown
is show, the listbox is there but empty (not showing the datasource content).
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;
}
}
The custom CtlDropdownPopup
is called like: (simplified)
private CtlCombobox LstCountry;
this.LstCountry.Source(dtCountries, "Country", "Country_ID");
As I said, the ToolStripDropDown
is shown with the listBox1
in it, but the list is empty. Curiously if I modify the Source()
method to
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());
}
}
}
The listbox is shown with the items on it. Although this workaround does the job, it is annoying not finding the answer of why can't I set the DataSource
directly (as I did directly in the first example), but manually having to add the items.
Any ideas will really help me to sleep well tonight :)
Thought #1: I believe since the same dtCountries
is linked to other ComboBox1.DataSource
, that may be the problem, so I set this.controlToPop.DataSource = dt.Copy();
in hopes "it is not somehow linked to the combobox", but the problem presists.
Side note: I am trying to create a custom combobox, that suggest items within the DataTable
.
Idea from https://www.codeproject.com/Tips/789705/Create-combobox-with-search-and-suggest-list