将列表绑定到数据源
Posted
技术标签:
【中文标题】将列表绑定到数据源【英文标题】:Bind List to DataSource 【发布时间】:2013-02-15 00:32:48 【问题描述】:我希望能够将列表绑定到列表框数据源,并且当列表被修改时,列表框的 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);
编辑:另外,我刚刚从 Ilia Jerebtsov 那里读到 List<T> vs BindingList<T> Advantages/DisAdvantages:“当您将 BindingSource 的 DataSource 设置为 List 时,它会在内部创建一个 BindingList 来包装您的列表”。我认为我的示例只是表明这是不正确的:我的 List 似乎没有在内部包装到 BindingList。
【问题讨论】:
List 不会引发任何事件让观察者知道何时更新。观察者是 UI 组件还是充当包装器的另一个列表并不重要。为什么在绑定时反对更改为 BindingList 是您需要做的? 我不想将 List 更改为 BindingList,因为它已经在项目中的任何地方用作 List。我将不得不替换每个方法签名,我想避免修改已经稳定的内容。 如果将返回类型更改为 IList您的示例中没有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
编辑
请注意(正如 cmets 中指出的那样)- bindingsource 不适用于 INotifyPropertyChanged
【讨论】:
这行得通。不幸的是,当 fooList 成员的 Bar 属性在别处更新时,ListBox 内容不会更新。这里有人对同样的问题感到恼火:social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/…【参考方案2】:试试
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";
之类的 Bar 成员时,它会更新 ListBox
但是,您必须将 ListBox 的 DisplayMember
属性设置为“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);
【讨论】:
感谢您的解决方案,但我发现 Jens Kloster 的解决方案更加优雅 :)以上是关于将列表绑定到数据源的主要内容,如果未能解决你的问题,请参考以下文章