I have a custom object that implements INotifyPropertyChanged. I have a collection of these objects where the collection is based on BindingList I have created a binding source for the collection, and set the datasources of the bindingsource and datagridview.
Everything works great, except I need to update properties on the custom object from background threads. when I do so, I get the following error :
BindingSource cannot be its own data source. Do not set the DataSource and DataMember properties to values that refere back to BindingSource
I found the following post that seems to have my exact problem (and solution?) but I cannot quite figure it out.
http://social.msdn.microsoft.com/forums/en-US/winformsdatacontrols/thread/3566f7c7-eb47-422e-ab09-9549a18da360/
I created and initialized the oper variables per the post in my business object, and then I put the two event functions into my collection class. This compiled correctly, but hangs without exception when run.
I have seen many posts saying to use Invoke/Begin Invoke, but I am not calling any functions on the UI, just updating business objects, so I am not sure where I would put the invoke calls.
One restriction : I want the business object to remain unaware of who is displaying it (as there are multiple consumers) so sending in GUI references into the business object so that I am later able to call invoke using those references is not an option.
I found this class in a forum that works. Just use this instead of BindingList
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Threading;
namespace Utility
{
public class ThreadedBindingList<T> : BindingList<T>
{
SynchronizationContext ctx = SynchronizationContext.Current;
protected override void OnAddingNew(AddingNewEventArgs e)
{
if (ctx == null)
{
BaseAddingNew(e);
}
else
{
ctx.Send(delegate
{
BaseAddingNew(e);
}, null);
}
}
void BaseAddingNew(AddingNewEventArgs e)
{
base.OnAddingNew(e);
}
protected override void OnListChanged(ListChangedEventArgs e)
{
// SynchronizationContext ctx = SynchronizationContext.Current;
if (ctx == null)
{
BaseListChanged(e);
}
else
{
ctx.Send(delegate
{
BaseListChanged(e);
}, null);
}
}
void BaseListChanged(ListChangedEventArgs e)
{
base.OnListChanged(e);
}
}
}
Since I took the time to format the sample for my needs I might as well post it here as a readable reference. Nothing changed except formatting.
using System.ComponentModel;
using System.Threading;
namespace Utility
{
public class ThreadedBindingList : BindingList
{
SynchronizationContext ctx = SynchronizationContext.Current;
protected override void OnAddingNew(AddingNewEventArgs e)
{
if (ctx == null)
{
BaseAddingNew(e);
}
else
{
ctx.Send(delegate { BaseAddingNew(e); }, null);
}
}
void BaseAddingNew(AddingNewEventArgs e)
{
base.OnAddingNew(e);
}
protected override void OnListChanged(ListChangedEventArgs e)
{
// SynchronizationContext ctx = SynchronizationContext.Current;
if (ctx == null)
{
BaseListChanged(e);
}
else
{
ctx.Send(delegate { BaseListChanged(e); }, null);
}
}
void BaseListChanged(ListChangedEventArgs e)
{
base.OnListChanged(e);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With