A: 

When you change the bound list content, you need to call ResetBindings().

Jeff Yates
Why would the Button2_Click() work then? ;)
Lucero
Quite possibly because other events that fire cause the binding to be reset internally.
Jeff Yates
Hm, the sampe is so simple that I don't see what other events should fire in that case compared to the other. But we'll see what Tobbe finds out.
Lucero
Is this needed even though I'm binding to a BindingList? My understanding is that the BindingList will raise a ListChanged event, that should make the listbox update itself.
Tobbe
It is my experience that this is not the case but YMMV.
Jeff Yates
You don't need to call ResetBindings() when you use BindingList. The IBindingList interface handles the bindings properly.
Justin Niessner
Thanks for confirming that. That's what I thought
Tobbe
+1  A: 

My guess is that this is due to the update message being handled on the wrong thread. Background: each thread has its own message queue. Messages posted into the message queue will land in the same thread as the caller by default. Therefore, the callback will maybe post a message on the wrong thread.

Try this: move the AddNumber() method to the form and use Invoke() (inherited by Control) to add the item in the correct thread. This may get rid of the issue.

Edit to reflect your followup: The UI doesn't have to know about your component. What you need is just a proper synchronization between adding the item to your list and the UI, since UI updates will oly work if the thread matches. Therefore, you might want to supply the Control to your class which wraps the BindingList, and then do the Invoke on the list itself. This makes the list worry about triggering the upate on the UI thread and does take the worry from both the UI and the external component of invoking the handler on the correct thread.

Like this:

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;
     }
    }
}
Lucero
I understand what the problem is, now we just have to come up with a good solution :)I'm trying to design this according to the MVC pattern, so letting ListBoxDataBindingSource (part of the Model) know about a control (part of the View) is generally seen as bad practice.
Tobbe
Well, it's not really knowing about the control, but only needs to know hot to marshal the add call to the correct thread. You could make your own marshaling class which knows about the control and is passed to the list, so that this aspect is properly hidden.
Lucero
A: 

Instead of having the setFP set the callback to lbDataBindingSource.AddNumber, create a private method in your code to handle the callback and then call lbDataBindingSource.AddNumber from that callback.

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

    cdll.setFP(FPCallback);
}

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