StackOverflowException with the ListChanged event

  • Thread starter Thread starter Joep
  • Start date Start date
J

Joep

Can you show us the ListChanged handler? StackOverflow => some (unintended,
unanticipated) loop that adds something with each iteration?
 
Hello group...

I've created a collection class that implements the following interfaces: IBindingList, IList, ICollection, IEnumerable and ITypedList:

abstract class DataCollectionBase : IBindingList, IList, ICollection, IEnumerable, ITypedList
{
private ArrayList innerList = null;
private System.Type itemType = null;

public DataCollectionBase()
{
this.innerList = new ArrayList();
}

protected System.Type ItemType
{
get { return this.itemType; }
set { this.itemType = value; }
}

// List Changed Notification
protected virtual void OnInsertComplete(int index, object newValue)
{
if (ListChanged != null)
{
ListChangedEventArgs args = new ListChangedEventArgs(ListChangedType.ItemAdded, index, -1);
ListChanged(this, args); // The StackOverflowException is thrown here
}
}

// IList Implementation
int IList.Add(object value)
{
int index = this.innerList.Add(value);
OnInsertComplete(index, value);
}

// IBindingList Implementation
public event ListChangedEventHandler ListChanged = null;

object IBindingList.AddNew()
{
object newItem = null;

// Here I create the new item with Reflection, based on the ItemType property and store a reference in 'newItem''.

((IList)this).Add(newItem);
return newItem;
}
}

I'm using my collection as a value for the DataSource property in a DataGrid control.
The IBindingList.AddNew() method works fine and the new item is instantiated via Reflection, but when I invoke the ListChanged event handler within the OnInsertComplete(..) method, the StackOverflowException is thrown.
I don't understand what's happening to my collection, the DataGrid control is the only component that's consuming the ListChanged event.

I really need your help...

Thank you all...
 
Could you perhaps provide the stack trace and, if possible, a short but
complete program[1] that exhibits your issue?
Its possible that there is something else in your application that is
causing the issue. Whittle down your code until it is nothing but the code
required to cause the problem. Although, contrary to the article, in this
case you would provide a GUI.

1. http://yoda.arachsys.com/csharp/complete.html (Its by Jon Skeet, another
C# MVP. I mention it only because the page itself is written in first person
and doesn't seem to mention who the author is.)
 
Hello Joep...

The ListChangedEventHandler is part of the .NET Framework and it's declared
under the System.ComponentModel namespace as follows:

public delegate void ListChangedEventHandler(object sender,
ListChangedEventArgs e);

and the IBindingList interface includes an event of that type.

interface IBindingList : IList, ICollection, IEnumerable
{
// Properties go here

event ListChangedEventHandler ListChanged;

// Methods go here
}

So, when my class implements the IBindingList interface I just have to write
something like this:

class DataCollectionBase : IBindingList, IList, ICollection, IEnumerable,
ITypedList
{
public event ListChangedEventHandler ListChanged = null;

protected virtual void OnInsertComplete(int index, object newValue)
{
if(ListChanged != null)
{
ListChangedEventArgs args = new
ListChangedEventArgs(ListChangedType.ItemAdded, index, -1);
ListChanged(this, args); // The StackOverflowException is thrown
here
}
}
}

As you can see, (from my point of view) I'm not doing anything strange with
the event.
Only the DataGrid control consumes the event behind the scenes with
something like:

((IBindingList)DataSource).ListChanged += new
ListChangedEventHandler(some_method);

At least that's what I think, please right me if I'm wrong...

Thank you all again...
 
Hello Daniel...

The Stack Trace:

at System.Windows.Forms.DataGrid.AddNewRow()
at System.Windows.Forms.DataGridAddNewRow.OnEdit()
at System.Windows.Forms.DataGrid.Edit(String instantText)
at System.Windows.Forms.DataGrid.Edit()
at System.Windows.Forms.DataGrid.OnEnter(EventArgs e)
at System.Windows.Forms.Control.NotifyEnter()
at System.Windows.Forms.ContainerControl.UpdateFocusedControl()


I just wrote this line in my main form constructor, after the
InitializeComponent() call:

this.dataGrid1.DataSource = myCollection; // myCollection is of a class
derived from DataCollectionBase, which I've described before...
// Right here the StackOverflowException is thrown.
// I ran my application in Debug mode and I went step by step into every
method call until I reached the ListChanged(..) invocation (the origin of
the exception).

Thank you for your help...
 
Daniel O'Connell said:
Could you perhaps provide the stack trace and, if possible, a short but
complete program[1] that exhibits your issue?
Its possible that there is something else in your application that is
causing the issue. Whittle down your code until it is nothing but the code
required to cause the problem. Although, contrary to the article, in this
case you would provide a GUI.

Not quite contrary to the article - it only says to remove GUI aspects
if they're unnecessary. A question *about* a GUI is fine to include a
GUI, of course - although it should be as pared down as possible.
1. http://yoda.arachsys.com/csharp/complete.html (Its by Jon Skeet, another
C# MVP. I mention it only because the page itself is written in first person
and doesn't seem to mention who the author is.)

That's a good point. Would you like me to rewrite it in the third
person, or perhaps put a "who wrote this" bit at the start?
 
Jon Skeet said:
Daniel O'Connell said:
Could you perhaps provide the stack trace and, if possible, a short but
complete program[1] that exhibits your issue?
Its possible that there is something else in your application that is
causing the issue. Whittle down your code until it is nothing but the
code
required to cause the problem. Although, contrary to the article, in this
case you would provide a GUI.

Not quite contrary to the article - it only says to remove GUI aspects
if they're unnecessary. A question *about* a GUI is fine to include a
GUI, of course - although it should be as pared down as possible.

Ya ya, I know. Don't need to be semantically precise do we? :)

My reading of the article suggests avoiding a GUI where possible and I just
wanted to make it clear that it is entirely appropriate here(although *it*
might have been possible to prove the bug without a GUI, atleast until I saw
the stack trace. I think its unlikely at this point). Although I could have
pointed it out in a different way.

Sorry for implying an error in your article, however, ;)
That's a good point. Would you like me to rewrite it in the third
person, or perhaps put a "who wrote this" bit at the start?

Being in the first person is fine, but I think atleast some accreditation is
in order. Something as simple as a "By Jon Skeet" would suffice nicely.
I don't want to appear to be claiming your work, afterall, ;).

One other point, however. You might want to suggest, for GUI related
questions, that the author take the extra step and avoid using the forms
designer(or any designer, for that matter, except where the designer is in
question). Right now its not too big of a deal, however, with the coming of
partial classes the forms designer is going to be one PITA to copy and paste
in. I worry we'll start to see
public partial class MyClass
{
//...
}
public partial class MyClass
{
private void InitalizeComponent()
{
//...
}
}
or simply two attached files.
 
Daniel O'Connell said:
Ya ya, I know. Don't need to be semantically precise do we? :)

My reading of the article suggests avoiding a GUI where possible and I just
wanted to make it clear that it is entirely appropriate here(although *it*
might have been possible to prove the bug without a GUI, atleast until I saw
the stack trace. I think its unlikely at this point). Although I could have
pointed it out in a different way.

Sorry for implying an error in your article, however, ;)

No problem. I'll amend the article to make it clearer.
Being in the first person is fine, but I think atleast some accreditation is
in order. Something as simple as a "By Jon Skeet" would suffice nicely.
I don't want to appear to be claiming your work, afterall, ;).

Righto. Have a look in a few minutes and let me know if the change is
okay.
One other point, however. You might want to suggest, for GUI related
questions, that the author take the extra step and avoid using the forms
designer(or any designer, for that matter, except where the designer is in
question). Right now its not too big of a deal, however, with the coming of
partial classes the forms designer is going to be one PITA to copy and paste
in. I worry we'll start to see
public partial class MyClass
{
//...
}
public partial class MyClass
{
private void InitalizeComponent()
{
//...
}
}
or simply two attached files.

Yup. Even now it makes the code less readable, IMO - and the more the
designer is used, the more the temptation is to have more controls
which aren't actually required.
 
Hello and thank you all

I've found the problem... this is my item class named EditableObject:

class EditableObject : IEditableObject
{
protected bool isUndefined;
protected bool isEditing;

public EditableObject()
{
this.isUndefined = true;
this.isEditing = false;
}

// IEditableObject interface
public void BeginEdit()
{
if (!this.IsUndefined)
{
if (this.innerRow != null)
{
this.innerRow.BeginEdit();
}
this.isEditing = true;
this.isUndefined = false;
}
}

public bool IsEditing
{
get { return this.isEditing; }
}

public bool IsUndefined
{
get { return this.IsUndefined; } // Here's the problem, IsUndefined instead of isUndefined (StackOverflowException) : )
}
}

When the collection is set as the data source for the DataGrid control and the datagrid is focused, a new item is added and the BeginEdit() method invoked.
This is a problem very hard to find, because I was focusing my atention to a totally diferent part of my program...

Thank you all...
 
Well, thtas good to hear.

That is another benifit of short but complete programs, if you write it and the error isn't there...there is ap retty good chance the error is elsewhere.

Glad you were able to solve your issue, however.
Hello and thank you all

I've found the problem... this is my item class named EditableObject:

class EditableObject : IEditableObject
{
protected bool isUndefined;
protected bool isEditing;

public EditableObject()
{
this.isUndefined = true;
this.isEditing = false;
}

// IEditableObject interface
public void BeginEdit()
{
if (!this.IsUndefined)
{
if (this.innerRow != null)
{
this.innerRow.BeginEdit();
}
this.isEditing = true;
this.isUndefined = false;
}
}

public bool IsEditing
{
get { return this.isEditing; }
}

public bool IsUndefined
{
get { return this.IsUndefined; } // Here's the problem, IsUndefined instead of isUndefined (StackOverflowException) : )
}
}

When the collection is set as the data source for the DataGrid control and the datagrid is focused, a new item is added and the BeginEdit() method invoked.
This is a problem very hard to find, because I was focusing my atention to a totally diferent part of my program...

Thank you all...
 
Being in the first person is fine, but I think atleast some accreditation
Righto. Have a look in a few minutes and let me know if the change is
okay.

Looks good. The additions about designers is effective as well.
 
It's good to know that we can always find someone like you that helps someone like me...

Thank you so much...
 
Back
Top