I want to display a custom collection in a DataGridView
in a Windows Forms app. This custom collection implements ICollection
, and IEnumerable
. I have set up a BindingSource
, using the collection as the .DataSource property. The DataGridView
is set to use my BindingSource
as it's DataSource. When I add a new item to the collection using the BindingSource.Add()
method, the DataGridView
updates correctly with the new item. The BindingSource
DataSource, on the other hand, does not:
MyCustomCollection myCollection = new MyCustomCollection();
myCollection.Add(myCustomObject1);
myCollection.Add(myCustomObject2);
myBindingSource.DataSource(myCollection);
myBindingSource.Add(myCustomObject3);
In the above code, myBindingSource's internal List contains the right number of records (3), and the DataGridView
also contains three records, but myCollection contains only two records. I know that changing the underlying myCollection will NOT update the BindingSource
or the DataGridView
, as it is not a BindingList<T>
, but I was under the impression that updating a BindingSource
directly would ensure that myCollection was updated at the same time.
Is there a way to use a collection that isn't a BindingList<T>
and have it updated when interacting with the BindingSource
directly?
Update: One way I've gotten the data updated across all the parts (Collection, BindingSource, DataGridView) is as follows:
myCollection.Add(myCustomObject3);
myBindingSource.DataSource = null;
myBindingSource.DataSource = myCollection;
I'm pretty sure there's a better way to attack this problem, but this is the only method that's generated the results I was expecting.
The problem is Fill Adaptor. When you load your form, the Fill is done for you.
Just make sure to do a Refill and then follow up with Reset bindings post any data changes and Grid will get refreshed.
Example :
WorkTableAdapter.Insert(objData.XAttribute, "",
objData.YAttribute,objLoanData.Amount_IsValid, DateTime.Now, DateTime.Now);
this.WorkTableAdapter.Fill(this.POCDataSet.Work);
this.WorkBindingSource.ResetBindings(false);
You will have to manually call ResetBindings() after the data source changes if you use a container that cannot do that on your behalf.
http://msdn.microsoft.com/en-us/library/system.windows.forms.bindingsource.resetbindings.aspx
Causes a control bound to the BindingSource to reread all the items in the list and refresh their displayed values.
I believe I ran into this issue a while ago - I did a find in files on my code and I think this is the solution that worked for me.
// Applies pending changes to the underlying data source.
this.bindingSource1.EndEdit();
This was in the context of a click handler for the save button.
Resetting an individual item works!
I had no luck with .ResetBindings(false) and re-assigning the datsource caused flickering with potentiail overhead if only one item change frequently.
I tried the built in mechanism using PropertyChanged but nothing updated.
Reseting an individual item using ResetItem() worked!
for (int i = 0; i < bindingSource1.Count; i++)
{
bindingSource1.ResetItem(i);
}
And even better - if you have an update event attached to each data item in the bindningsource you can locate the object in the bindning source and use the index of the object to call ResetItem(idx)
In this case my custom event args contains a dictionary key to the data object contained in a separate collection. After object is located in using bindningsource.IndexOf() it is individually refreshed.
void Value_PropertyChanged(object sender, RegisterEventArgs e)
{
var idx = bindingSource1.IndexOf(registers_ref[e.registerID]);
if (idx>=0)
{
bindingSource1.ResetItem(idx);
}
}