将列表绑定到数据源

本文关键字:数据源 绑定 列表 | 更新日期: 2023-09-27 18:01:31

我希望能够将列表绑定到列表框数据源,当列表被修改时,列表框的UI会自动更新。(Winforms不是ASP)。下面是一个示例:

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_;
    }
}

如果我用BindingList<Foo> fooList = new BindingList<Foo>();代替List<Foo> fooList = new List<Foo>();,那么它可以工作。但我不想改变傻瓜的原始类型。我希望这样的工作:listBox1.DataSource = new BindingList<Foo>(fooList);

编辑:我也只是在这里读列表vs BindingList来自Ilia Jerebtsov的优点/缺点:"当你将BindingSource的数据源设置为list <>时,它会在内部创建一个BindingList来包装你的列表"。我认为我的示例只是证明了这不是真的:我的List<>似乎并没有在内部包装成BindingList<>

将列表绑定到数据源

你的例子中没有BindingSource

你需要像这样修改它来使用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

编辑

请注意(正如在评论中指出的那样)- bindingsource不适用于INotifyPropertyChanged

Try

listBox1.DataSource = new BindingList<Foo>(fooList);
然后

private void button1_Click(object sender, EventArgs e)
{
    Foo foo2 = new Foo("bar2");
    (listBox1.DataSource as BindingList<Foo>).Add(foo2);
}

这将更新傻瓜而不必改变其原始类型。同样,当你改变Bar成员,如fooList[1].Bar = "Hello";

时,它会更新ListBox。

然而,你必须将ListBox的DisplayMember属性设置为"Bar",以保持。tostring()覆盖在Foo类定义中。

为了避免每次都必须强制转换,我建议您在与列表定义相同的级别上使用BindingList变量:

private List<Foo> fooList;
private BindingList<Foo> fooListUI;
fooListUI = new BindingList<Foo>(fooList);
listBox1.DataSource = fooListUI;

和按钮:

Foo foo2 = new Foo("bar2");
fooListUI.Add(foo2);