添加到ToolStripDropDown时,Listbox DataSource无法正常工作

时间:2018-05-13 03:28:22

标签: c# winforms 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时,列表框就在那里但是空(不显示数据源内容)。

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 个答案:

答案 0 :(得分:1)

您需要设置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控件或将其作为参数传递)

希望有所帮助。