简体   繁体   中英

Bind List to DataSource

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<>.

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

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);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM