添加到 ToolStripDropDown 时列表框数据源不起作用
Listbox DataSource not working when added to a ToolStripDropDown
虽然我找不到解决方案,但我整天都在为这个问题苦苦挣扎。很抱歉post,我尽量简洁明了
这是可行的:我创建了一个 Form
并在其 class 中动态创建了一个 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
时,列表框在那里但为空(不显示数据源内容)。
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();
希望 "it is not somehow linked to the combobox",但问题仍然存在。
旁注:我正在尝试创建一个自定义组合框,建议 DataTable
中的项目。
想法来自 https://www.codeproject.com/Tips/789705/Create-combobox-with-search-and-suggest-list
您需要设置ListBox的BindingContext
属性。
当 ListBox (或任何控件) 添加到窗体时,它会从窗体继承其 BindingContext
属性。现在,由于您将 ListBox 添加到另一个带有 .BindingContext == null
的 TopLevel 控件,它不会从表单继承 属性,因此,它没有 BindingContext
.
您可以通过为 ListBox 创建一个新的 BindingContext
来简单地避免这个问题:
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
控件或将其作为参数传递).
希望对您有所帮助。
虽然我找不到解决方案,但我整天都在为这个问题苦苦挣扎。很抱歉post,我尽量简洁明了
这是可行的:我创建了一个 Form
并在其 class 中动态创建了一个 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
时,列表框在那里但为空(不显示数据源内容)。
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();
希望 "it is not somehow linked to the combobox",但问题仍然存在。
旁注:我正在尝试创建一个自定义组合框,建议 DataTable
中的项目。
想法来自 https://www.codeproject.com/Tips/789705/Create-combobox-with-search-and-suggest-list
您需要设置ListBox的BindingContext
属性。
当 ListBox (或任何控件) 添加到窗体时,它会从窗体继承其 BindingContext
属性。现在,由于您将 ListBox 添加到另一个带有 .BindingContext == null
的 TopLevel 控件,它不会从表单继承 属性,因此,它没有 BindingContext
.
您可以通过为 ListBox 创建一个新的 BindingContext
来简单地避免这个问题:
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
控件或将其作为参数传递).
希望对您有所帮助。