Источник данных 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 управление или путем передачи его в качестве параметра).

Надеюсь, это поможет.

Другие вопросы по тегам