Источник данных Listbox не работает при добавлении в ToolStripDropDown - PullRequest
0 голосов
/ 13 мая 2018

Я весь день боролся с этой проблемой, хотя не мог найти решение. Я прошу прощения за длинный пост, я старался быть кратким и ясным.

Вот что работает : я создаю 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 голосов
/ 13 мая 2018

Вам необходимо установить свойство 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, либо с помощьюпередавая его в качестве параметра) .

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

...