Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating of BindingSource in WinForms does not update Datasource Collection

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.

like image 838
Jeff Clare Avatar asked Jan 28 '13 21:01

Jeff Clare


4 Answers

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);
like image 108
Frank Avatar answered Oct 16 '22 06:10

Frank


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.

like image 20
Eric J. Avatar answered Oct 16 '22 08:10

Eric J.


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

    }
like image 34
tofo Avatar answered Oct 16 '22 07:10

tofo


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.

like image 36
Aaron Anodide Avatar answered Oct 16 '22 08:10

Aaron Anodide