I'd like to have a basic ListBox with associated Add and Delete buttons. The Delete button be enabled if and only if there is a selection in the ListBox, and the Add button should append an item to the end of the ListBox.
My first attempt was to just make a List<string> items
field, like so:
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>();
}
But, it turns out that the ListBox does not seem to update automatically as the items in the list change. Here's a related question about it.
Most advice suggested just running listBox1.DataSource = null; this.listBox1.DataSource = this.items;
every time I updated the list, but that to me defeats the purpose of binding.
Another answer suggested using an ObservableCollection
for my list's data type, but that did nothing different.
Finally I found the BindingList
class and it seemed to do what I want; the ListBox automatically reflects the contents of the items
field. (If there is another solution that is actually a best practice and not some piece of cargo cult folklore pasted around the Internet, please let me know.)
However, when the first item I add to items
appears in the ListBox, the row becomes selected. And I can see that listBox1.SelectedIndex
changes from -1 to 0. But, the listBox1_SelectedIndexChanged
event does not fire. Hence, the state of the Delete button doesn't get updated properly.
(As an aside, this UI pattern is extremely commonplace, and it seems disastrous that there's so much conflicting information on implementing such a simple thing.)