Invalid Operation Exception when adding Collection to Binding Source

S

simonrigby_uk

Hello all,

Firstly, this is a .NET 2.0 issue. (C#)

I have a DataGridView and a dataset that has been generated by the
wizard from a strongly typed collection. In my form_load I am
attempting to add an instance of this collection to the BindingSource

eg.

gridBindingSource.Add(myStronglyTypedCollectionInstance);

I am getting an Invalid Operation Exception (Objects added to a
BindingSource's list must all be of the same type).

The collection in question is a strongly typed collection of abstract
objects. That is, I have an abstract class which is generalised by two
sub classes. I have built a collection to hold the abstracts.

Note this happens even though the collection is empty.

Is this a limitation of the BindingSource?

Any help greatly appreciated.

Cheers

Simon
 
C

Cor Ligthert [MVP]

Simon,

We will gladly help C# questions as well in this newsgroup. However the
newsgroup is more focused on VB Net, so it can become very confusing is you
get C# help here for people who are searching for information later.

In my opinion is the DataGridView however an elment from the Data section
and than in my idea is that even more for the newsgroup.

microsoft.public.dotnet.framework.adonet

I hope you find your answer soon,

Cor.
 
C

Cor Ligthert [MVP]

Simon,

Murphy is on the run with me.

Doh, I was thinking that I was answering from the VB net newsgroup, excuse
me very very very much.

:)

Cor
 
S

simonrigby_uk

microsoft.public.dotnet.framework.adonet

which part of the above group name refers to C#. By the way, you quote
this in your message as the newsgroup I should post to and yet this IS
the group I have posted to.

Secondly the object in question is not part of the DataGridView, it is
the BindingSource.

Any help still greatly appreciated.

Cheers

Simon
 
B

Bart Mermuys

Hi,

Hello all,

Firstly, this is a .NET 2.0 issue. (C#)

I have a DataGridView and a dataset that has been generated by the
wizard from a strongly typed collection.

Didn't you mean a DataSource is created from a typed collection ? I'm not
sure if or how you can create a DataSet from a typed collection.

A BindingSource can only be backed by _one_ Collection, DataSet, DataTable
or DataView and it's set using the DataSource property.

If you have created a DataSource from your typed collection and dragged it
on the Form or assigned it to the DataGridView.DataSource then it will
connect by setting a BindingSource inbetween, the BindingSource will create
an instance of the typed collection which you can access like:
StronglyTypedCollection instance =
(StronglyTypedCollection)gridBindingSource.List;

If not, you can do it from code:
gridBindingSource.DataSource = myStronglyTypedCollectionInstance

Then gridBindingSource.Add can be used to add single objects to the
StrongyTypedCollection it manages.

HTH
Greetings
 
S

Simon

Hi Bart,

Sorry, yes my mistake, I have created a DataSource from the collection.

Effectively I have a "container" object which contains an instance of a
strongly typed collection of abstracts which is generalised by two
conrete classes:

ie.

Survey which contains an instance QuestionCollection

QuestionCollection is typed to Question which is abstract

Question is generalised by TextQuestion and OptionQuestion

My main form contains a textbox and a DataGridView. The texboxes "text"
property is bound to a property of Survey (Survey.Title). This creates
the appropriate BindingSource (surveyBindingSource) and in my code I
call the BindingSource's Add method to add the instance of the Survey I
want it to bind to.

So far so good. The textbox displays Survey.Title as I expect.

I now set the DataGridView's DataSource to the questions property
exposed by expanding the surveyBindingSource's branch in the DataSource
dialog and selecting the Questions property contained within it.

I call a dialog box that returns an instance of TextQuestion which is
added to my Survey instance. However, the contents of the DataGridView
don't change.

At this point I have tried to Add the collection to the DataGridViews
appropriate binding source.

ie

questionsBindingSource.Add(_survey.Questions);

However, this throws an InvalidOperationException(Objects added to a
BindingSource's list must all be of the same type.)

Still confused!!!

Hope this gives someone more to go on.

Cheers

Simon
 
B

Bart Mermuys

Hi Simon,

Simon said:
Hi Bart,

Sorry, yes my mistake, I have created a DataSource from the collection.

Effectively I have a "container" object which contains an instance of a
strongly typed collection of abstracts which is generalised by two conrete
classes:

ie.

Survey which contains an instance QuestionCollection
QuestionCollection is typed to Question which is abstract
Question is generalised by TextQuestion and OptionQuestion

Ok, no problem.
My main form contains a textbox and a DataGridView. The texboxes "text"
property is bound to a property of Survey (Survey.Title). This creates the
appropriate BindingSource (surveyBindingSource)

Yes, i guess you're binding to your Survey-DataSource Title, which indeed
creates a SurveyBindingSource which is backed by a BindingList said:
and in my code I call the BindingSource's Add method to add the instance
of the Survey I want it to bind to.

Yes said:
So far so good. The textbox displays Survey.Title as I expect.

Shows the title of the first Survey. (which you added).
I now set the DataGridView's DataSource to the questions property exposed
by expanding the surveyBindingSource's branch in the DataSource dialog and
selecting the Questions property contained within it.

Perfect, that's exactly how you should do it. After you do that a new
BindingSource ( QuestionsBindingSource ) should appear. Don't forget to
create the columns if they weren't auto created.
I call a dialog box that returns an instance of TextQuestion which is
added to my Survey instance. However, the contents of the DataGridView
don't change.

Well, it *should* already.

1) Sure you add the TextQuestion to the right Survey ( the one you already
added using SurveyBindingSource )?

2) What kind of "Custom Collection" is QuestionCollection really ? Is it a
At this point I have tried to Add the collection to the DataGridViews
appropriate binding source.
ie
questionsBindingSource.Add(_survey.Questions);
However, this throws an InvalidOperationException(Objects added to a
BindingSource's list must all be of the same type.)

Yeah, i want to stress here, that you *don't* need to do that. I should
already work without this.

HTH,
Greetings
 
S

Simon

Ahhh. No my collection inherits from CollectionBase.

Interestingly enough I tried setting the DGV's DataSource to the same
surveyBindingSource and then set the DataMember to the Questions
property of it. Still no joy with display, however using either method
still sets the appropriate columns in the DataGridView at design and run
time. Yes it is adding to the correct Survey instance.

Effectively I am opening a dialog that creates an instance of a text
question which i expose by a public property. If the DialogResult
returns OK I get the dialog's TextQuestion instance and add it.

ie

TextQuestionForm f = new TextQuestionForm();
if (f.ShowDialog == DialogResult.OK) {
_survey.Questions.Add(f.Question);
}

However, I'm intrigued by your mention of IBindingList or the use of a
generic. Is this something I've missed?

Many thanks for your help. I really appreciate it.

Cheers

Simon
 
B

Bart Mermuys

Hi,

Simon said:
Ahhh. No my collection inherits from CollectionBase.

Interestingly enough I tried setting the DGV's DataSource to the same
surveyBindingSource and then set the DataMember to the Questions property
of it. Still no joy with display, however using either method still sets
the appropriate columns in the DataGridView at design and run time. Yes it
is adding to the correct Survey instance.

Effectively I am opening a dialog that creates an instance of a text
question which i expose by a public property. If the DialogResult returns
OK I get the dialog's TextQuestion instance and add it.

ie

TextQuestionForm f = new TextQuestionForm();
if (f.ShowDialog == DialogResult.OK) {
_survey.Questions.Add(f.Question);
}

However, I'm intrigued by your mention of IBindingList or the use of a
generic. Is this something I've missed?

Yes, a collection that only inherits from CollectionBase can't *notify* the
BindingSource/DGV that it has changed. (eg. that there are new items)

So, either you inherit from BindingList<Question> like:

public class QuestionCollection : BindingList<Question>
{
// BindingList<Question> provides typed Methods like:
// Add, Remove, IndexOf and it implements IBindingList so
// it can notify the BindingSource/DGV that it has changed
}

Alternative you can still inherit from CollectionBase and implement
IBindingList yourself:

public class QuestionCollection : CollecitonBase, IBindingList
{
// implement the typed methods yourself
// implement IBindingList yourself
// see
http://msdn.microsoft.com/msdnmag/issues/05/08/CollectionsandDataBinding/default.aspx
}

It's a lot easier to inherit from BindingList<T> ( NET2.0 only) then it is
to implement
IBindingList yourself.

HTH,
Greetings
 
S

Simon

Right, got ya. Clear as mud. No just kidding. Completely understand.

Legendary response. A good day's work for you. Get your self a beer
(religion permitting).

Cheers

Simon
 
S

Simon

Marvelous marvelous marvelous .. Yup changed the collection to inherit
from BindingList and everything works as expected.

Thanks once again Bart. Very much appreciated.

Simon
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top