My app adds nodes in 2 ways.
In one case it specifies both a key and text.In the other it specifies text only (null key)
Occasionally [for no obvious reason] the tree is replaced by a large red X and a message box says Item has already been added. Key in dictionary: "Teradata SQL"
This occurs in response to an event - not due to a call from within my code. (It seems to be a Paint event - see trace below)
The problem is that I have searched my entire source base (including resource files) and the only time the string "Teradata SQL" is used it is used for the TEXT property - not the KEY.
Could the Tree somehow get confused if I am adding the nodes within a BeginUpdate/EndUpdate block and specifying a null key?
How can a paint event (which I have no handler for) cause it to attempt to add a node?
Is there any way to trap this error?Maybe add a Paint handler that simply calls your paint handler from inside a catch block ... but I think it is too late by then.
Traceback:
System.ArgumentException: Item has already been added. Key in dictionary: 'Teradata SQL' Key being added: 'Teradata SQL' at System.Collections.Hashtable.Insert(Object key, Object nvalue, Boolean add) at System.Collections.Hashtable.Add(Object key, Object value) at Infragistics.Win.UltraWinTree.NodeClientAreaUIElement.CacheNodeElements(Hashtable table, UIElementsCollection oldElements, Int32 startIndex) at Infragistics.Win.UltraWinTree.NodeClientAreaUIElement.PositionChildElements() at Infragistics.Win.UIElement.VerifyChildElements(ControlUIElementBase controlElement, Boolean recursive) at Infragistics.Win.UIElement.VerifyChildElements(Boolean recursive) at Infragistics.Win.UIElement.VerifyChildElements() at Infragistics.Win.UltraWinTree.UltraTreeUIElement.PositionChildElements() at Infragistics.Win.UIElement.VerifyChildElements(ControlUIElementBase controlElement, Boolean recursive) at Infragistics.Win.UIElement.DrawHelper(Graphics graphics, Rectangle invalidRectangle, Boolean doubleBuffer, AlphaBlendMode alphaBlendMode, Boolean clipText, Boolean forceDrawAsFocused, Boolean preventAlphaBlendGraphics) at Infragistics.Win.ControlUIElementBase.Draw(Graphics graphics, Rectangle invalidRectangle, Boolean doubleBuffer, AlphaBlendMode alphaBlendMode, Size elementSize, Boolean preventAlphaBlendGraphics) at Infragistics.Win.ControlUIElementBase.Draw(Graphics graphics, Rectangle invalidRectangle, Boolean doubleBuffer, AlphaBlendMode alphaBlendMode) at Infragistics.Win.UltraControlBase.OnPaint(PaintEventArgs pe) at Infragistics.Win.UltraWinTree.UltraTree.OnPaint(PaintEventArgs pe) at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer, Boolean disposeEventArgs) at System.Windows.Forms.Control.WmPaint(Message& m) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
ThanksMike
Okay, Mike. Let me know how it goes.
If possible, I recommend testing your application without any background worker threads and see if that helps, too.
It's possible that the threading could be causing a problem with some static resource that is being shared between all WinTree controls in the same application. This is yet another reason why threading issues are so hard to track down.
None of the above.
The data that is added to this tree is simply the type of the database connection. That type string is determined when the user connects to the database, which is all done in the main thread.
If the user expands this node the child data is read directly from a file - again on the main thread.
Depending on the users settings, the data loaded into the OTHER tree may be loaded asyncronously and that might be occuring at the time that this tree is loaded. (although the tester tells me not)
Just in case the async loading of the other tree is somehow interfering with the simple load (of 2 'known' nodes) into this tree I will switch the order to load this tree before calling the function to load the other tree.
I'll let you know if that helps. (May be a weekk or so)
Hi Mike,
mikedempsey said:If I use the Add(key, text) function and specify the key as an empty string is that still treated as having no key? (or would that be classed as a key with the value of a zero length string?)I'm asking because I 'cleaned up' the code and started to do it that way. It works exactly the same for me in both cases - ie. it works fine, but I have not yet sent the new version to the tester who is seeing the Red X problem.
I'm not sure off the top of my head, but this is very easy to test. Put a new tree control on a form and try to add two nodes with empty strings as keys. I tried this out with empty strings and with nulls and it works fine for me. So it appears that null or empty string are both treated as a null key and either one is fine.
mikedempsey said:The application does use worker threads to do some things such as executing a database query, but all interaction with this Tree is done from the main thread.
Every indication here is that this is a threading issue, so I would be very suspicious of any code in your application that is using threading.The fact that I suspected a threading issue before I even knew your application was using threads and then it turned out that you actually are using threads seems to me to be a pretty strong indication that threads are the problem.
If you were adding nodes to the tree that actually had duplicate keys, then the exception would not be occurring when the tree paints, it would happen when you tried to add the node.
Using a worker thread to retrieve data from a database can easily cause problems that are very hard to detect. Threading issues are notorious difficult to track down, because the actual exception you get occurs long after the real problem happened and often appears to be completely unrelated to the actual problem.
Are you using DataBinding in your application at all? Are you binding the tree or any of it's nodes? Are you populating the tree from this data that you retrieved on the worker thread?
The application does use worker threads to do some things such as executing a database query, but all interaction with this Tree is done from the main thread.
I do have a second Tree that is loaded asyncronously ... but I'm not having any trouble with that one.
If I use the Add(key, text) function and specify the key as an empty string is that still treated as having no key? (or would that be classed as a key with the value of a zero length string?)I'm asking because I 'cleaned up' the code and started to do it that way. It works exactly the same for me in both cases - ie. it works fine, but I have not yet sent the new version to the tester who is seeing the Red X problem.
The node it complains about was not added within a Begin/EndUpdate. It is a one off addition of a single node which is bypassed by the line before it if the node already exists. that's what makes me think it is getting confused somewhere. Either it is reporting the wrong key in the error message (what it reports as the key was in fact the Text) or else it is reading its cache incorrectly.
I am using Windows Forms version 11.2.20112.2019
Nodes with no keys don't count when considering unique keys. So if a node has a key, it must be unique, but a node with no key is no problem. You can have as many keyless nodes as you want.
Is your code, in fact, adding nodes with duplicate keys? If so, then the tree should be blowing up when you try to add the node, not in the Paint event. I don't think using BeginUpdate or EndUpdate has anything to do with this, but I could be wrong. There's a very easy way to tell - simply remove the BeginUpdate and EndUpdate call and see if that makes the error occur outside of the Paint event.
My best guess about this exception is one of two things:
1) Your application is using multiple threads and they are getting out of synch because you are not properly marshaling the data across threads.Are you using threads in your application?
2) This is a bug in the tree control. What version of the controls are you using?
EDIT: Are you able to reproduce this exception reliably? If so, posting a small sample project demonstrating the exception would allow us to track it down.
EDIT: Never mind, you already answered that question.
I took a look at the code where the exception is occurring and it looks like what's happening here is that the tree is caching some UIElements for the nodes. This is an optimization for efficiency. The only way I can see that an exception like this could occur is if there is more than one TreeNodeUIElement referencing the same node, which should never happen. So a threading issue would be my first guess.