Home > Software design >  ComboBox has DataSource set but is not displaying any items
ComboBox has DataSource set but is not displaying any items

Time:09-17

I have a windows form with a ComboBox DisplayBox. In my ViewModel I now have a Property BindingList<MyObject> ObjectBindingList that I want to bind to the DisplayBox.

When I load the form, the DisplayBox does not show any text.

The property DataSource is set and holds a List of MyObjects when checking in the debug modus after the data download. The property items always has a count of zero.

My code works as following:

On startup I set the databindings in the form class to a still empty List ObjectBindingList.

displayBox.DataSource = ObjectBindingList;

The DisplayMember and ValueMember were set in the ComboBox Properties in the GUI Designer.
Asynchrously the controller downloads some data (MyDataObjects) async. Then sets the BindingList<MyObject> ObjectBindingList in the ViewModel to the downloaded Objects through adding them.

CodePudding user response:

It seems like when trying to update the ComboBox from a different thread than the main forms thread, the update did not reach the control. I am now using the Invoke Method together with a BindingSource Object in between the Binding List and the control.

private void SetBindingSourceDataSource( BindingList<MyObject> myBindingList)
{
    if (InvokeRequired)
    {
        Invoke(new Action<BindingList<MyObject>>(SetBindingSourceDataSource),  myBindingList);
    }
    else {
        this.BindingSource.DataSource = myBindingList;
    }
}

I am expeciall calling the above function on a PropertyChanged event, that I trigger at the end of every call of the download Function.

CodePudding user response:

Since I don't see all of the relevant code, I can only assume what's happening.

Probably, you don't see the data in the ComboBox, because you are creating a new BindingList when loading the data. But the ComboBox is still attached to the old empty list.

You initialize the data source with an empty list like this:

// Property
BindingList<MyObject> ObjectBindingList { get; set; }

Somewhere else

// Initializes data source with an empty `BindingList<MyObject>`.
ObjectBindingList = new BindingList<MyObject>();
displayBox.DataSource = ObjectBindingList;

Later, you load the data and replace the list:

ObjectBindingList  = LoadData();

Now, you have two lists: the initial empty list assigned to displayBox.DataSource and a new filled one assigned to the property ObjectBindingList. Note that displayBox.DataSource does not have a reference to the property itself, therefore it does not see the new value of the property.

For a BindingList<T> to work as intended, you must add the items with

var records = LoadData();
foreach (var data in records) {
    ObjectBindingList.Add(data);
}

I.e., keep the original BindingList<MyObject> assigned to the data source.


See also: How can I improve performance of an AddRange method on a custom BindingList?


To avoid the problem, I would be advisasble to make the property read-only (using C# 9.0's Target-typed new expressions).

BindingList<MyObject> ObjectBindingList { get; } = new();
  • Related