Reputation: 918
I want to be able to bind a list to a listbox datasource and when the list is modified, the listbox's UI automatically updated. (Winforms not ASP). Here is a sample :
private List<Foo> fooList = new List<Foo>();
private void Form1_Load(object sender, EventArgs e)
{
//Add first Foo in fooList
Foo foo1 = new Foo("bar1");
fooList.Add(foo1);
//Bind fooList to the listBox
listBox1.DataSource = fooList;
//I can see bar1 in the listbox as expected
}
private void button1_Click(object sender, EventArgs e)
{
//Add anthoter Foo in fooList
Foo foo2 = new Foo("bar2");
fooList.Add(foo2);
//I expect the listBox UI to be updated thanks to INotifyPropertyChanged, but it's not
}
class Foo : INotifyPropertyChanged
{
private string bar_ ;
public string Bar
{
get { return bar_; }
set
{
bar_ = value;
NotifyPropertyChanged("Bar");
}
}
public Foo(string bar)
{
this.Bar = bar;
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
public override string ToString()
{
return bar_;
}
}
If I replace List<Foo> fooList = new List<Foo>();
by BindingList<Foo> fooList = new BindingList<Foo>();
then it works. But I don't want to change the original type of foolist. I would like something like this to work : listBox1.DataSource = new BindingList<Foo>(fooList);
EDIT : Also I just read here List<T> vs BindingList<T> Advantages/DisAdvantages from Ilia Jerebtsov : "When you set a BindingSource's DataSource to a List<>, it internally creates a BindingList to wrap your list". I think my sample just demonstrates that this is not true : my List<> doesn't seem to be internally wrapped into a BindingList<>.
Upvotes: 9
Views: 45526
Reputation: 18051
Try
listBox1.DataSource = new BindingList<Foo>(fooList);
then
private void button1_Click(object sender, EventArgs e)
{
Foo foo2 = new Foo("bar2");
(listBox1.DataSource as BindingList<Foo>).Add(foo2);
}
This will update fooList without having to change its original type. Also, it will update the ListBox when you change the Bar member like fooList[1].Bar = "Hello";
However, you will have to set the DisplayMember
property of the ListBox to "Bar", or to keep the .ToString() override as is in the Foo class definition.
In order to avoid to have to cast every time, I suggest you to use a BindingList variable at the same level as your List definition :
private List<Foo> fooList;
private BindingList<Foo> fooListUI;
fooListUI = new BindingList<Foo>(fooList);
listBox1.DataSource = fooListUI;
and in the button :
Foo foo2 = new Foo("bar2");
fooListUI.Add(foo2);
Upvotes: 6
Reputation: 11287
You don't have a BindingSource in you example.
you need to modify it like this to use a BindingSource
var bs = new BindingSource();
Foo foo1 = new Foo("bar1");
fooList.Add(foo1);
bs.DataSource = fooList; //<-- point of interrest
//Bind fooList to the listBox
listBox1.DataSource = bs; //<-- notes it takes the entire bindingSource
Edit
Be aware that (as was pointed out in comments) - the bindingsource does not work with INotifyPropertyChanged
Upvotes: 8