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();