9

我希望能够将列表绑定到列表框数据源,并且在修改列表时,列表框的 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_;
    }
}

如果我更换List<Foo> fooList = new List<Foo>();BindingList<Foo> fooList = new BindingList<Foo>();那么它的工作原理。但我不想改变原来的傻瓜类型。我想要这样的工作:listBox1.DataSource = new BindingList<Foo>(fooList);

编辑:另外,我刚刚在这里阅读了Ilia Jerebtsov 的List<T> vs BindingList<T> 的优点/缺点:“当您将 Bi​​ndingSource 的 DataSource 设置为 List<> 时,它会在内部创建一个 BindingList 来包装您的列表”。我认为我的示例只是表明这是不正确的:我的 List<> 似乎没有在内部包装到 BindingList<> 中。

4

2 回答 2

8

您的示例中没有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

于 2013-02-28T19:43:18.183 回答
6

尝试

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

这将更新 fooList 而无需更改其原始类型。此外,当您更改 Bar 成员时,它会更新 ListBoxfooList[1].Bar = "Hello";

但是,您必须将DisplayMemberListBox 的属性设置为“Bar”,或者保持 .ToString() 覆盖与 Foo 类定义中的一样。

为了避免每次都必须强制转换,我建议您使用与 List 定义相同级别的 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);
于 2013-02-28T17:58:59.173 回答