绑定列表到数据源
问题描述:
我希望能够将列表绑定到列表框数据源,并且当列表被修改时,列表框的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);
编辑:另外我刚刚读到这里List<T> vs BindingList<T> Advantages/DisAdvantages从伊利亚Jerebtsov:“当你设置一个的BindingSource的DataSource到一个列表<>,它在内部创建一个的BindingList包列表”。我认为我的示例只是证明这不是真的:我的清单<>似乎没有内部包装到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
答
尝试
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而无需改变其原来的类型。此外,当你改变杆件类似fooList[1].Bar = "Hello";
但是它会更新列表框,你将不得不设置列表框“酒吧”,或的DisplayMember
属性来保持的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);
列表不会引发观察员知道何时更新的任何事件。观察者是一个UI组件还是充当包装的另一个列表并不重要。为什么在绑定时反对更改为绑定列表是您需要做的事情? – JRoughan 2013-02-28 18:20:18
我不想将列表更改为BindingList,因为它已经在项目的任何地方用作列表。我将不得不更换每个方法签名,我想避免修改已经稳定的内容。 – Michael 2013-02-28 18:26:17
如果您将退货类型更改为IList,该怎么办?你是否仍然有相同数量的重大变化? –
JRoughan
2013-02-28 19:25:17