Update: I checked the answer before I fully tested it still does not work. I updated the code below so you should just be able to paste in to a empty WinForms project and it
Use a BindingList instead of a List
. It was designed to address such issues. Dinesh Chandnani, a member of the .NET Client Team, states the following in a blog post:
BindingList<T>
is the new generic implementation of IBindingList which fires ListChanged event when items are added/removed/inserted/etc. from the list. bindingSource hooks on to these events and is thus “aware” of these changes and can notify controls bound thos this BindingSource.
I was able to reproduce the issue you described in your updated entry, but didn't quite reproduce the original issue without tweaking the code slightly.
By using a BindingList<Holder>
I was able to get an immediate response when focus left the textbox. It's possible to get instant updates by using an overloaded method when adding a new data binding. I also set the BindingSource
's DataSource
directly since using a null
dataMember
in the overloaded constructor was not yielding the expected behavior.
Here's the code I ended up with based off your sample code:
public partial class Form1 : Form
{
private BindingSource bs;
private BindingList<Holder> bList;
public Form1()
{
InitializeComponent();
bList = new BindingList<Holder>();
bList.Add(new Holder("test1"));
bList.Add(new Holder("test2"));
bs = new BindingSource();
bs.DataSource = bList;
cmb.DataSource = bs;
cmb.DisplayMember = "Name";
cmb.ValueMember = "Name";
// updates when focus leaves the textbox
txt.DataBindings.Add("Text", bs, "Name");
// updates when the property changes
//txt.DataBindings.Add("Text", bs, "Name", false, DataSourceUpdateMode.OnPropertyChanged);
}
}
Comment out the first txt
binding and uncomment the one below it to see the DataSourceUpdateMode.OnPropertyChanged in action.
Here are some BindingList
resources:
1) Replace bsBroken = new BindingSource(lstBroken, null);
with:
bsBroken = new BindingSource();
bsBroken.DataSource = lstBroken;
Or in one line: bsBroken = new BindingSource() { DataSource = lstBroken };
This yields the expected behavior with an immediate response to changes (I also mentioned this before above). Do not use the overload that accepts a dataMember
and set it to null. Doing so gives the buggy behavior you're experiencing.
2) After doing the above, I see no need for the txtBroken_TextChanged
event. Comment out the event handler assignment to test, but you should be able to remove it completely.