I have the bound my DataGridView
to BindingSource
but when I call ResetBinding()
the DataGridView
doesn't get updated to show only those records which have WhenDeleted column value as null:
public partial class LabourSetup : DisplayControl
{
private List<LABOUR> labourCollection = new List<LABOUR>();
protected BindingSource bs = new BindingSource();
private void PopulateGrid()
{
labourCollection = Query.GetLabours();
bs.DataSource = labourCollection;
this.dataGridViewX1.DataSource = bs;
}
// This method doesn't actually delete Labour from table just mark the column with the present day date. So that it could not be shown in Grid View
public void btnDel_Click(object sender, EventArgs e)
{
if(dataGridViewX1.SelectedRows.Count == 1)
{
dataGridViewX1.SelectedRows[0].Cells["WhenDeleted"].Value = DateTime.Now;
}
MainForm.GlobalCache.SaveChanges();
labourCollection = Query.GetLabours();
//bs.DataSource = labourCollection; // works when I un comment this line
bs.ResetBindings(false); // doesnt work
}
}
}
In above, why do I have to write:
//bs.DataSource = labourCollection; // works when I un comment this line. Why?
Since binding source is already bound to labourCollection in PopulateGrid() method. ResetBinding() should not show record marked for deletion(WhenDeleted not null).
public class Query
{
internal static List<LABOUR> GetLabours()
{
// Getting only those records which are not marked for deletion
return MainForm.GlobalCache.LABOURs.Local.Where(lab => lab.WhenDeleted == null).ToList();
}
}
In above GlobalCache
is DbContext
.
Help is appreciated.
Why this code doesn't work?
labourCollection = Query.GetLabours();
bs.ResetBindings(false);
Let's see the reason. There are 2 problem in above code:
labourCollection = Query.GetLabours();
doesn't have any impact on DataSource
of bs
. It just assigns a new list to labourCollection
variable. But previous list is still in memory. labourCollection
just points to the new list, but bs
uses the list which you assigned to its DataSource
property. So the changed item is still there in the list which you used as DataSource
of bs
.
Remember reference type concepts. If you assign a new object to a variable, the previous object is untouched. You just missed the pointer to that object and the variable points to the new object.
ResetBindings
method just causes a control bound to the BindingSource
to reread all the items in the list and refresh their displayed values. It doesn't reload data from database or somewhere else. It just look into DataSource
and shows data in the bound control again. So the the value which you changed will be there in list and you can not expect the ResetBindings
perform anything special for you.
So why the this code works?
labourCollection = Query.GetLabours();
bs.DataSource = labourCollection;
bs.ResetBindings(false);
It works because of bs.DataSource = labourCollection;
. The last line of code is useless. When you assign a new list to DataSource
of BindingSource
it cause refreshing bound controls and you don't need to call ResetBindings
.
What's the usage of ResetBindings?
It's useful to refresh grid to show values from data source, when the data source doesn't support 2-way data-binding.
If you change a property of LABOUR
in the list using labourCollection[0].Property = "Value";
or even if you remove an item from the list using labourCollection.RemoveAt(0);
the DataGridView
will not show new value of the Property
or even it's not aware of removed item.
If you call bs.ResetBindings(false)
the DataGridView
shows new value of property. Also doesn't show the removed item.
labourCollection[0].SomeProperty = "Some Value";
bs.ResetBindings(false);