2013-02-28 55 views
7

Tôi muốn có thể liên kết danh sách với nguồn dữ liệu danh sách và khi danh sách được sửa đổi, giao diện người dùng của hộp danh sách sẽ tự động được cập nhật. (Winforms không ASP). Đây là một mẫu:Danh sách liên kết tới DataSource

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

Nếu tôi thay List<Foo> fooList = new List<Foo>(); bởi BindingList<Foo> fooList = new BindingList<Foo>(); sau đó nó hoạt động. Nhưng tôi không muốn thay đổi kiểu người ngu ngốc ban đầu. Tôi muốn một cái gì đó như thế này để làm việc: listBox1.DataSource = new BindingList<Foo>(fooList);

EDIT: Ngoài ra tôi chỉ đọc ở đây List<T> vs BindingList<T> Advantages/DisAdvantages từ Ilia Jerebtsov: "Khi bạn thiết lập DataSource của BindingSource vào một danh sách <>, nó trong nội bộ tạo ra một BindingList quấn danh sách của bạn". Tôi nghĩ rằng mẫu của tôi chỉ chứng minh rằng điều này là không đúng: Danh sách của tôi <> dường như không được bao bọc bên trong vào một BindingList <>.

+0

Danh sách <> không tăng bất kỳ sự kiện nào cho người quan sát để biết thời điểm cập nhật. Việc người quan sát là thành phần giao diện người dùng hay danh sách khác hoạt động như một trình bao bọc không quan trọng. Tại sao sự phản đối để thay đổi thành một BindingList khi ràng buộc là những gì bạn cần làm? – JRoughan

+0

Tôi không muốn thay đổi Danh sách thành BindingList vì nó đã được sử dụng làm Danh sách ở mọi nơi trong dự án. Tôi sẽ phải thay thế mọi phương thức chữ ký, tôi muốn tránh sửa đổi những gì đã ổn định. – Michael

+0

Điều gì xảy ra nếu bạn thay đổi kiểu trả về thành IList ? Bạn vẫn có cùng số lượng thay đổi đột phá? – JRoughan

Trả lời

7

Bạn không có ví dụ BindingSource.

bạn cần phải sửa đổi nó như thế này để sử dụng một 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 

Sửa

Hãy nhận biết rằng (như đã được chỉ ra trong ý kiến) - BindingSource không làm việc với INotifyPropertyChanged

+0

Tác phẩm này. Thật không may, nội dung ListBox không được cập nhật khi thuộc tính Bar của thành viên fooList được cập nhật ở nơi khác. Có một người bị làm phiền bởi cùng một vấn đề ở đây: http://social.msdn.microsoft.com/Diễn đàn/en-US/netfxbcl/thread/f54c125f-6f53-4446-9088-a193f6474059 – Larry

+0

@Laurent điểm tốt. Tôi không biết điều đó. Câu trả lời đã chỉnh sửa –

+0

Tuyệt vời, hoạt động tuyệt vời. – Michael

5

Hãy thử

listBox1.DataSource = new BindingList<Foo>(fooList); 

sau đó

private void button1_Click(object sender, EventArgs e) 
{ 
    Foo foo2 = new Foo("bar2"); 
    (listBox1.DataSource as BindingList<Foo>).Add(foo2); 
} 

này sẽ cập nhật fooList mà không cần phải thay đổi loại ban đầu của nó. Ngoài ra, nó sẽ cập nhật các ListBox khi bạn thay đổi thành viên Bar như fooList[1].Bar = "Hello";

Tuy nhiên, bạn sẽ phải thiết lập các DisplayMember tài sản của ListBox để "Bar", hay để giữ ToString() ghi đè như là trong định nghĩa lớp Foo.

Để tránh phải đúc mọi thời gian, tôi đề nghị bạn sử dụng một biến BindingList ở mức tương tự như định nghĩa Danh sách của bạn:

private List<Foo> fooList; 
private BindingList<Foo> fooListUI; 

fooListUI = new BindingList<Foo>(fooList); 
listBox1.DataSource = fooListUI; 

và trong nút:

Foo foo2 = new Foo("bar2"); 
fooListUI.Add(foo2); 
+0

Cảm ơn giải pháp của bạn nhưng tôi đã tìm thấy giải pháp của Jens Kloster hơn một chút thanh lịch :) – Michael

+1

Tôi tôn trọng điều này! :-) – Larry

Các vấn đề liên quan