views:

1968

answers:

3

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.

+2  A: 

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);
        }
    } 
}
Jason Coyne
A: 

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);
    }
  }
}
VVS
A: 

Thanks you so much!!!

This class fixed an error I've been very frustrated with for a long time! It seems that when BindingList is the source for a BindingSource attached to a DataGridView, there are times when the BindingList.Add() method can fail. The error that is generated is a cryptic InvalidOperationException with the message "Operation is not valid due to the current state of the object." Your implementation of OnAddingNew() Addressed this.

Thanks Tons!

Guy