9

リストをリストボックス データソースにバインドできるようにしたいのですが、リストが変更されると、リストボックスの UI が自動的に更新されます。(ASPではなくWinform)。ここにサンプルがあります:

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> Advantages/DisAdvantagesを読みました:「BindingSource の 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

編集

(コメントで指摘されているように)注意してください-バインディングソースは機能しません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メンバーを変更すると、ListBoxが更新されます。fooList[1].Bar = "Hello";

ただし、DisplayMemberListBoxのプロパティを「Bar」に設定する、Fooクラス定義のように.ToString()オーバーライドを維持する必要があります。

毎回キャストする必要がないように、リスト定義と同じレベルで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 に答える