2009-04-20 35 views
5

Hình ảnh dưới đây cho biết cách mã của tôi hoạt động. Khi tôi nhấn button2, hộp danh sách được cập nhật, nhưng không phải khi tôi nhấn button1. Tại sao?Hộp danh sách Winforms không cập nhật khi thay đổi dữ liệu bị ràng buộc

pseudo code http://i44.tinypic.com/mj69oj.gif

Sự cố có liên quan đến luồng không? Nếu có, tôi nên thêm cuộc gọi vào đâu (Bắt đầu) Gọi?

Một điều thú vị cần lưu ý là nếu tôi lần đầu tiên nhấn button1 và sau đó button2 dữ liệu được tạo ra bởi nút button1 được hiển thị khi tôi nhấp vào button2. Vì vậy, có vẻ như dữ liệu do doFoo tạo ra được đệm ở đâu đó và sau đó được đẩy vào hộp danh sách khi tôi nhấn button2.

EDIT:

Tôi đã thử thêm AddNumber vào mã hình thức, và thêm một cuộc gọi đến Gọi khi listBox1.InvokeRequired trả về true. Điều này giải quyết vấn đề, nhưng không phải là thiết kế đẹp nhất. Tôi không muốn GUI phải "lo lắng" về cách thêm các mục vào danh sách là một phần của mô hình.

Làm cách nào để giữ logic đằng sau việc thêm vào danh sách bên trong danh sách lớp, trong khi vẫn cập nhật gui khi danh sách thay đổi?

EDIT 2:

Bây giờ chúng ta đã xác nhận rằng đây là một vấn đề luồng Tôi đã cập nhật hình ảnh để phản ánh chặt chẽ hơn việc thiết kế các mã thực tế tôi đang làm việc trên.

Trong khi đề xuất của Lucero vẫn giải quyết được vấn đề, tôi đã hy vọng một điều gì đó không yêu cầu biểu mẫu biết bất cứ điều gì về dll hoặc CDllWrapper.

Mô hình

(ListBoxDataBindingSource vv) nên biết gì cả về quan điểm (listboxes, nút, nhãn vv)

Trả lời

2

tôi đoán là điều này là do thông báo cập nhật được xử lý trên thread sai. Bối cảnh: mỗi luồng có hàng đợi thông báo của riêng nó. Các tin nhắn được đăng vào hàng đợi tin nhắn sẽ nằm trong cùng một chuỗi với người gọi theo mặc định. Do đó, cuộc gọi lại có thể sẽ gửi một thông báo trên chuỗi sai.

Hãy thử điều này: di chuyển phương thức AddNumber() vào biểu mẫu và sử dụng Invoke() (được kế thừa bởi Điều khiển) để thêm mục vào chuỗi chính xác. Điều này có thể loại bỏ vấn đề.

Chỉnh sửa để phản ánh việc theo dõi của bạn: Giao diện người dùng không phải biết về thành phần của bạn. Những gì bạn cần chỉ là một đồng bộ hóa thích hợp giữa việc thêm mục vào danh sách của bạn và giao diện người dùng, vì cập nhật giao diện người dùng sẽ làm việc nếu chuỗi phù hợp. Vì vậy, bạn có thể muốn cung cấp điều khiển cho lớp của bạn mà kết thúc tốt đẹp BindingList, và sau đó làm Invoke trên danh sách chính nó. Điều này làm cho danh sách lo lắng về việc kích hoạt upate trên thread UI và không lo lắng từ cả UI và thành phần bên ngoài của việc gọi trình xử lý trên luồng chính xác.

Như thế này:

internal class ListBoxDataBindingSource { 
    private readonly Control uiInvokeControl; 
    private readonly BindingList<Item> list = new BindingList<Item>(); 

    public ListBoxDataBindingSource(Control uiInvokeControl) { 
     if (uiInvokeControl == null) { 
      throw new ArgumentNullException("uiInvokeControl"); 
     } 
     this.uiInvokeControl = uiInvokeControl; 
     CDIIWrapper.setFP(AddNumber); 
    } 

    public void AddNumber(int num) { 
     Item item = new Item(num.ToString()); 
     if (uiInvokeControl.InvokeRequired) { 
      uiInvokeControl.Invoke(list.Add, item); 
     } else { 
      list.Add(item); 
     } 
    } 

    private BindingList<Item> List { 
     get { 
      return list; 
     } 
    } 
} 
+0

Tôi hiểu vấn đề là gì, bây giờ chúng tôi chỉ cần đưa ra một giải pháp tốt :) Tôi đang cố thiết kế mẫu này theo mẫu MVC, vì vậy hãy để ListBoxDa taBindingSource (một phần của Model) biết về một điều khiển (một phần của View) thường được xem là thực hành không tốt. – Tobbe

+0

Vâng, nó không thực sự biết về kiểm soát, nhưng chỉ cần biết nóng để sắp xếp các cuộc gọi thêm vào các chủ đề chính xác. Bạn có thể làm cho lớp marshaling của riêng bạn biết về điều khiển và được chuyển vào danh sách, để khía cạnh này được ẩn đi đúng cách. – Lucero

+0

(* @ Tobbe: * Có thể [câu trả lời này] (http://stackoverflow.com/questions/3381536/winforms-data-binding-to-business-objects-in-a-multi-threaded-scenario-without-in/3381685 # 3381685) cho một trong những câu hỏi trước đây của tôi - [Winforms dữ liệu ràng buộc với các đối tượng kinh doanh trong một kịch bản đa luồng mà không có InvokeRequired?] (Http://stackoverflow.com/q/3381536/240733) - sẽ áp dụng ở đây.) – stakx

0

Thay vì có các setFP thiết lập callback để lbDataBindingSource.AddNumber, tạo ra một phương pháp riêng trong mã của bạn để xử lý các cuộc gọi lại và sau đó gọi lbDataBindingSource.AddNumber từ callback đó.

void MyForm_Load(object sender, EventArgs e) 
{ 
    //... 

    cdll.setFP(FPCallback); 
} 

private void FPCallback(int num) 
{ 
    lbDataBindingSoruce.AddNumber(num); 
} 
1

Tôi biết điều này là cũ, mặc dù tôi đã có một vấn đề rất giống nhau.

Đây là giải pháp: BindingList not updating bound ListBox.

+0

Cảm ơn bạn. Tôi đặt dự án này trên băng một thời gian dài trước đây, nhưng khi tôi nhặt nó lên một lần nữa tôi sẽ thấy nếu điều đó giúp :) – Tobbe

0

tôi cần phải gọi mô hình quan điểm của tôi để thêm điều cần các BindingList, vì vậy tôi cần phải viết một chức năng ẩn danh

tham khảo để trả lời Lucero và sau bài: Anonymous method in Invoke call

Mã của tôi:

listBox.Invoke((Action)delegate 
{ 
    MyViewModel.AddItem(param1, param2); 
}); 
Các vấn đề liên quan