I've updated my project from 8.3 release to 11.1. I did not introduce any changes to the code but the application stopped working.
it hangs on the following line: itemGrid.DataSource = value
itemGrid is UltraGrid, value is List<MyClass>
itemGrid.InvokeRequired is false
by hangs I mean that application is not responding and taking whole CPU - as if ultraGrid is in some kind of infinite loop
any idea how to track the bug?
Hi,
I just wanted to know if you were able to solve your issue based onmy suggestions or you still need help? Just let me know.
Thank you.
Hello again!
I've postponed the upgrade till now. The problem still occurs, even in version 11.2. The symptom is the same as before.
I disabled "Just My Code" debugging. This allowed me to see why does it hang on assigning the DataSource.
Let's say we bind an empty list (Enumerable.Empty) to a data source of a type defined as follows:
public interface IGroup
{
IEnumerable<IGroup> RecursiveList { get; }
KeyedCollection<int, IGroup> ChildGroups { get; }
}
Of course the interface is more rich, but for sake of clarity let it be that thin.
The part of the call stack is in the attachment.
Unfortunately I can't post the full code, but I've managed to create a simple project that may be helpful in solving the problem.
Actually I was not able to reproduce the hanging issue. Instead it shows that assigning data source may be bugged. Have a look at it and follow the comment inside IRecursive interface to see strange UltraGrid behaviour.The point is that when ChildGroups is defined as generic ICollection the message pops up. When you change its type to KeyedCollection, the message is not displayed. Seems a bug to me.
I'm looking forward to your reply.
Regards,
Pokrec
Hi Pokrec,
I ran your sample and I don't get any message. I just get an empty grid.
The problem here is that IEnumerable is not a valid data source for databinding to the WinGrid. Your data source needs to implement either IList or IBindingList.I recommend using BindingList<T> for best results.
It appears that your data source is also recursive and therefore has an unlimited depth. This might be what is causing your application to hang. This issue, and some potential solutions, are discussed in detail in the WinGrid Performance Guide in the section entitled Recursion.
Hi Mark,
Have you changed the IRecursive interface as I asked you? The point is that depending on the property type the message is shown or not. I would like to know why it is so.
If you say that IEnumerable is not supported by WinGrid DataSource, why there is no NotSupportedException thrown? Current behaviour is very confusing.
I'm aware that binding is very limited without BindingList, but why isn't it supported? Version 2008 handled them well. Could you point me some article where you describe breaking backwards compatibility in this area?
I'll check the guide, thanks.
PoKrec said:Have you changed the IRecursive interface as I asked you?
No, I didn't. Your post jumped around a bit, so I thin I just missed that part.I tried it now and I see that there is a difference in behavior like you are describing.
If you set the Visual Studio IDE to break on all run-time exception, you will see that the reason the MessageBox does not get hit is because an exception is being raised. You aren't seeing it, because Microsoft made a change (I beleive in VS2010) where they are now catching exceptions that occur in the Form_Load and handling them.
The exception occurs because of the way the BindingManager in DotNet works.
The grid is binding to the root level of your data just fine. In the case of the KeyedCollection, the KeyedCollection class inherits from Collection, which implements the IList interface. Since it's an IList, the grid determines that this should be displayed as a child list.
But the Dotnet BindingManager is unable to determine the data structure for this list. It has no way of getting from KeyedCollection to the columns that should be displayed in the grid.
In a case where the child data structure cannot be determined by the type, the BindingManager tries to add a row to the collection. Once there is a row, it examines it to get it's public properties, then it cancel this new row. But there is no way for the BindingManager to create a new instance of a row in this case, because your row data is not a concrete class, but is instead an Interface.
So it fails with an exception.
The reason the exception does not occur with ICollection is because the ICollection is neither an IList nor an IBindingList. Therefore, the grid treats it like a normal column and not a child list. It doesn't even try to get the structure.
I'm not sure how this could ever have worked in any previous version of NetAdvantage. None of what's happening here has anything to do with the grid as far as I can see - it's all about how the BindingManager works.