2011-01-28 35 views
6

Tôi có một số ListBox được ràng buộc với một BindingList. BindingList được tạo khi ứng dụng của bên thứ ba tăng sự kiện. Tôi có thể thấy BindingList bị ràng buộc chính xác ... nhưng không có gì nhập vào ListBox. Tôi đã sử dụng chính xác cùng một logic với một số loại tùy chỉnh của riêng tôi và nó thường hoạt động rất tốt.BindingList không cập nhật bị ràng buộc ListBox

lớp Mẫu lớp

private Facade.ControlFacade _controlFacade;   
public UavControlForm() 
{ 
    InitializeComponent(); 
    _controlFacade = new UavController.Facade.ControlFacade();  
    UpdateEntityListBox(); 
} 
private void UpdateEntityListBox() 
{ 
    lsbEntities.DataSource = _controlFacade.GetEntityTally(); 
    lsbEntities.DisplayMember = "InstanceName"; 
} 

Facade

private Scenario _scenario; 
public ControlFacade() 
{ 
    _scenario = new Scenario(); 
} 
public BindingList<AgStkObject> GetEntityTally() 
{ 
    BindingList<AgStkObject> entityTally = _scenario.EntityTally; 
    return entityTally; 
} 

lớp Kịch bản

private static BindingList<IAgStkObject> _entityTally = new BindingList<AgStkObject>(); 
public Scenario() 
{ 
    if (UtilStk.CheckThatStkIsAvailable()) 
    { 
     UtilStk.StkRoot.OnStkObjectAdded += new IAgStkObjectRootEvents_OnStkObjectAddedEventHandler(TallyScenarioObjects); 
     UtilStk.StkRoot.OnStkObjectDeleted += new IAgStkObjectRootEvents_OnStkObjectDeletedEventHandler(TallyScenarioObjects); 
    }   
} 
private void TallyScenarioObjects(object sender) 
{ 
    List<AgStkObject> tallyOfStkObjects = UtilStk.GetRunningTallyOfAllStkObjects(); 
    List<string> stkObjectNames = UtilStk.GetInstanceNamesOfStkObjects(tallyOfStkObjects); 

    foreach (string stkObjectName in stkObjectNames) 
    { 
     if (!SearchFlightUavTallyByName(stkObjectName)) 
     { 
      if (!SearchLoiterUavTallyByName(stkObjectName)) 
      { 
       if (!SearchEntityTallyByName(stkObjectName)) 
       { 
        int i = stkObjectNames.IndexOf(stkObjectName); 
        _entityTally.Add(tallyOfStkObjects[i]); 
       } 
      } 
     } 
    } 
} 

tôi có thể thấy e lỗ thông hơi từ ứng dụng của bên thứ ba - điều này thêm một thực thể vào _entityList như mong muốn, nhưng không được thêm vào lsbEntities - tại sao?

Trả lời

11

(nhảy ngay đến các ví dụ cuối cùng nếu bạn muốn nhìn thấy nó cố định vv)

Chủ đề và "quan sát viên" mô hình (chẳng hạn như dữ liệu bắt buộc đối với winforms) bạn bè hiếm khi tốt. Bạn có thể thử thay thế việc sử dụng BindingList<T> của mình bằng mã ThreadedBindingList<T> mà tôi đã sử dụng trên previous answer - nhưng sự kết hợp các chủ đề và giao diện người dùng này không phải là trường hợp sử dụng cố định của ràng buộc dữ liệu winform.

listbox tự nên hỗ trợ ràng buộc thông qua các sự kiện thông báo danh sách (IBindingList/IBindingListView), miễn là họ đến hình thành các chủ đề ngay. ThreadedBindingList<T> cố gắng sửa lỗi này bằng cách chuyển đổi chủ đề nhân danh bạn. Lưu ý rằng để làm việc này, bạn phải phải tạo ThreadedBindingList<T> từ chuỗi giao diện người dùng, sau nó có ngữ cảnh đồng bộ hóa, tức là sau khi nó bắt đầu hiển thị biểu mẫu.


Để minh họa cho quan điểm rằng ListBox không tôn trọng thông báo danh sách thay đổi (khi giao dịch với một chủ đề duy nhất):

using System; 
using System.ComponentModel; 
using System.Windows.Forms; 
class Foo 
{ 
    public int Value { get; set; } 
    public Foo(int value) { Value = value; } 
    public override string ToString() { return Value.ToString(); } 
} 
static class Program 
{ 
    [STAThread] 
    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     using(var form = new Form()) 
     using (var lst = new ListBox()) 
     using (var timer = new Timer()) 
     { 
      var data = new BindingList<Foo>(); 
      form.Controls.Add(lst); 
      lst.DataSource = data; 
      timer.Interval = 1000; 
      int i = 0; 
      timer.Tick += delegate 
      { 
       data.Add(new Foo(i++)); 
      }; 
      lst.Dock = DockStyle.Fill; 
      form.Shown += delegate 
      { 
       timer.Start(); 
      }; 
      Application.Run(form); 
     } 
    } 
} 

và bây giờ với thêm luồng/ThreadedBindingList<T> (nó doesn 't làm việc với thông thường BindingList<T>):

using System; 
using System.ComponentModel; 
using System.Threading; 
using System.Windows.Forms; 
class Foo 
{ 
    public int Value { get; set; } 
    public Foo(int value) { Value = value; } 
    public override string ToString() { return Value.ToString(); } 
} 
static class Program 
{ 
    [STAThread] 
    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     using(var form = new Form()) 
     using (var lst = new ListBox()) 
     { 
      form.Controls.Add(lst);    
      lst.Dock = DockStyle.Fill; 
      form.Shown += delegate 
      { 
       BindingList<Foo> data = new ThreadedBindingList<Foo>(); 
       lst.DataSource = data; 
       ThreadPool.QueueUserWorkItem(delegate 
       { 
        int i = 0; 
        while (true) 
        { 
         data.Add(new Foo(i++)); 
         Thread.Sleep(1000); 
        } 
       }); 
      }; 
      Application.Run(form); 
     } 
    } 
} 
public class ThreadedBindingList<T> : BindingList<T> 
{ 
    private readonly SynchronizationContext ctx; 
    public ThreadedBindingList() 
    { 
     ctx = SynchronizationContext.Current; 
    } 
    protected override void OnAddingNew(AddingNewEventArgs e) 
    { 
     SynchronizationContext ctx = SynchronizationContext.Current; 
     if (ctx == null) 
     { 
      BaseAddingNew(e); 
     } 
     else 
     { 
      ctx.Send(delegate 
      { 
       BaseAddingNew(e); 
      }, null); 
     } 
    } 
    void BaseAddingNew(AddingNewEventArgs e) 
    { 
     base.OnAddingNew(e); 
    } 
    protected override void OnListChanged(ListChangedEventArgs e) 
    { 
     if (ctx == null) 
     { 
      BaseListChanged(e); 
     } 
     else 
     { 
      ctx.Send(delegate 
      { 
       BaseListChanged(e); 
      }, null); 
     } 
    } 
    void BaseListChanged(ListChangedEventArgs e) 
    { 
     base.OnListChanged(e); 
    } 
} 
+0

Cảm ơn! Tôi chỉ muốn thử điều này. Tôi không chắc chắn tại sao - trong mã của tôi - một chủ đề khác đang được sử dụng? Tôi không xác định rõ ràng để sử dụng. Bạn có thể cho tôi biết lý do tại sao? – wulfgarpro

+2

Không chỉ có các ví dụ của bạn đã giúp tôi hiểu bản chất của các chủ đề trong WinForms; Tôi đã học về Thread Pooling, Delegates và Event Handling. Cảm ơn bạn rất nhiều vì đã dành thời gian và công sức. Với cơ sở này, bây giờ tôi có thể hiểu rõ hơn về C# và phát triển phần mềm nói chung. – wulfgarpro

+0

@WulfgarPro - trên một vài loại (BindingSource có thể?) Có một sự kiện được tăng lên khi ràng buộc không thành công. Nếu bạn đăng ký sự kiện này, bạn có thể nhận được nhiều thông tin hơn về các thông báo lỗi nếu không thì im lặng. –

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