2009-04-20 51 views
5

下圖顯示了我的代碼如何工作。當我按下按鈕2時,列表框被更新,但不是當我按下按鈕1時。爲什麼?當綁定的數據發生變化時,Winforms listbox不會更新

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

是線程相關的問題?如果是,我應該在哪裏添加調用(Begin)Invoke?

一個有趣的事情要注意的是,如果我先按下按鈕1,然後按下按鈕2 button1生成的數據點擊顯示當我點擊button2。所以看起來doFoo產生的數據被緩衝到某個地方,然後一旦我按下按鈕2就將其推送到列表框。

編輯:

我嘗試添加AddNumber到表單代碼,並添加調用調用時listBox1.InvokeRequired返回true。這解決了這個問題,但並不是最好的設計。我不希望GUI必須「擔心」如何將項目添加到模型的一部分列表中。

如何保持添加到列表類內部列表的邏輯,同時在列表更改時仍然更新gui?

編輯2:

現在,我們已經確認這是一個線程問題我已經更新了圖像更密切地反映我工作的實際代碼的設計。

雖然Lucero的建議仍然解決了這個問題,但我希望有一些不需要表單的知道任何有關dll或CDllWrapper的東西。

模型(ListBoxDataBindingSource等)應該知道什麼都沒有對視圖(列表框,按鈕,標籤等)

回答

2

我的猜測是,這是由於更新消息錯誤的線程上被處理。背景:每個線程都有自己的消息隊列。發佈到消息隊列中的消息默認情況下將與主叫方在同一線程中。因此,回調可能會在錯誤的線程中發佈消息。

嘗試此操作:將AddNumber()方法移動到窗體並使用Invoke()(由Control繼承)將項添加到正確的線程中。這可能會解決問題。

編輯反映您的後續行動: 用戶界面不必知道您的組件。你需要的只是將項目添加到列表和UI之間的適當同步,因爲如果線程匹配,UI更新將會起作用。因此,您可能想要將Control提供給包裝BindingList的類,然後在列表本身上執行Invoke。這使得列表擔心在UI線程上觸發upate,並且擔心UI和外部組件都會在正確的線程上調用處理程序。

像這樣:

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

我明白是什麼問題,現在我們只需要想出一個好的解決方案:) 我試圖根據MVC模式設計這個,所以讓ListBoxDa taBindingSource(模型的一部分)知道控件(視圖的一部分)通常被認爲是不好的做法。 – Tobbe 2009-04-20 15:51:57

+0

嗯,它並不是真正瞭解控件,但只需要知道熱將編組調用添加到正確的線程即可。你可以讓自己的編組類知道控制權,並將其傳遞給列表,以便正確隱藏這個方面。 – Lucero 2009-04-20 16:38:45

0

而是具有setFP的設置回調lbDataBindingSource.AddNumber,創建你的代碼來處理回調的私有方法,然後從回撥電話lbDataBindingSource.AddNumber。

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

    cdll.setFP(FPCallback); 
} 

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

我需要調用我的視圖模型添加東西到的BindingList,所以我需要編寫一個匿名函數

參考盧塞羅的答案和下面的帖子: Anonymous method in Invoke call

我的代碼:

listBox.Invoke((Action)delegate 
{ 
    MyViewModel.AddItem(param1, param2); 
}); 
相關問題