绑定列表更新时不会触发ListBox SelectedIndexChanged事件

时间:2018-07-02 12:47:53

标签: c# winforms listbox

我想要一个基本的ListBox以及相关的Add和Delete按钮。当且仅当在列表框中有一个选择项时,才启用“删除”按钮,并且“添加”按钮应将一个项目附加到列表框的末尾。

我的第一个尝试是仅创建一个List<string> items字段,就像这样:

public partial class Form1 : Form {
    public Form1 {
        InitializeComponent();
        this.listBox1.DataSource = this.items;
    }

    private void addButton_Click(object sender, EventArgs e) {
        this.items.Add("item {this.items.Count + 1}");
    }

    private void deleteButton_Click(object sender, EventArgs e) {
        this.items.RemoveAt(this.listBox1.SelectedIndex);
    }

    private void listBox1_SelectedIndexChanged(object sender, EventArgs e) {
        this.deleteButton.enabled = (this.listBox1.SelectedIndex != -1);
    }

    List<string> items = new List<string>();
}

但是,事实证明,随着列表中项目的更改,列表框似乎并没有自动更新。 Here's a related question

大多数建议都建议每次我更新列表时都只运行listBox1.DataSource = null; this.listBox1.DataSource = this.items;,但对我而言,这违反了绑定的目的。

另一个答案建议使用ObservableCollection作为我列表的数据类型,但这没什么不同。

最后,我找到了BindingList类,它似乎可以满足我的要求。 ListBox会自动反映items字段的内容。 (如果还有另一种实际上是最佳实践的解决方案,而不是在Internet上粘贴一些不道德的民间传说,请让我知道。)


但是,当我添加到items的第一项出现在列表框中时,该行被选中。而且我可以看到listBox1.SelectedIndex从-1变为0。但是,listBox1_SelectedIndexChanged事件不会触发。因此,“删除”按钮的状态无法正确更新。

(顺便说一句,这种UI模式是极端司空见惯,而关于实现这种简单操作的信息如此之多,似乎是灾难性的。)

2 个答案:

答案 0 :(得分:0)

我也遇到了同样的问题。由于这是我遇到的第一个问题,所以也许我的答案可以节省一些时间。

DataSource分配一个空的BindingList并在以后将项目添加到该BindingList中,就像这样:

private BindingList<MyType> _myList = new BindingList<MyType>();

public MyForm()
{
    listBox1.DataSource = _myList;
}

private void LoadData()
{
    foreach (MyType item in GetDataFromSomewhere())
    {
        _myList.Add(item);
    }
}

然后添加第一项后,将在ListBox中选择,而listBox1.SelectedIndex将为0-但不会触发SelectedIndexChanged事件。

herehere所示,这可能是ListBox中的错误。

一种解决方法可能是从ListBox导出为Juan did,或者只是在添加之前检查BindingList是否包含任何项目:

        bool isFirstItem = (0 == _myList.Count);
        _myList.Add(item);
        if (isFirstItem)
        {
            // Your choice: set listBox1.SelectedIndex to -1 and back to 0,
            // or call the event handler yourself.
        }

答案 1 :(得分:-1)

尝试手动选择最后一个元素,而不要依赖默认行为。这将触发事件。

public partial class Form1 : Form
{
    BindingList<string> items = new BindingList<string>();
    public Form1()
    {
        InitializeComponent();
        this.listBox1.DataSource = items;
    }

    private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
    {
        this.deleteButton.Enabled = (this.listBox1.SelectedIndex != -1);
    }

    private void addButton_Click(object sender, EventArgs e)
    {
        this.items.Add($"item {this.items.Count + 1}");
        this.listBox1.SelectedIndex = -1;
        this.listBox1.SelectedIndex = this.listBox1.Items.Count - 1;
    }

    private void deleteButton_Click(object sender, EventArgs e)
    {
        this.items.RemoveAt(this.listBox1.SelectedIndex);
    }
}