リストをリストボックスデータソースにバインドできるようにしたいのですが、リストが変更されると、リストボックスのUIが自動的に更新されます。 (ASPではなくWinforms)。ここにサンプルがあります:
_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>();
に置き換えると、機能します。しかし、私は元のタイプのfoolistを変更したくありません。このようなものを機能させたい:listBox1.DataSource = new BindingList<Foo>(fooList);
編集:また、私はここを読んだ List <T> vs BindingList <T> Advantages/DisAdvantages from 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
では機能しないことに注意してください
試してみてください
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が更新されます。
ただし、Fooクラス定義のように.ToString()オーバーライドを維持するには、ListBoxのDisplayMember
プロパティを "Bar"、またはに設定する必要があります。
毎回キャストする必要がないように、リスト定義と同じレベルで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);