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
Hello ,
If you try to add a UltraTreeNode to UltraTree Nodes collection, and the key of this node already exist into the UltraTree Nodes collection, then you will get ArgumetException . If you use Add(string value) method then the new added node will have as a key the value which you were pas as parameter. I am not exactly sure why you get this red X and as you said this kind of issues happens with painting of the component, so I assume that you are adding your nodes in some background thread and that is why the exeption is trough in the background thread and the result is in the main UI thread. My suggestion is to add your nodes in BeginUpdate()/EndUpdate() bloc and to check if there already exist a node with the same key. To do this you could use code like:
if(ultraTree1.GetNodeByKey(key) == null)
ultraTree1.Nodes.Add(key);
Please let me know if you have any further questions.
That's the problem - I already do what you suggest.
I use Add(Key, Text) in most cases and the value it is complaining about is specified in the Text parameter - never the Key parameter.(Only one item is added at a time so I dont use BeginUpdate/EndUpdate here)
In another place I use Add() and then specify the Text - but not the Key - so the key defaults to something like 'Node34'.(This is the case that adds multiple nodes so I do use BeginUpdate/EndUpdate here)
In addition, when I use the Add(Key,Text) function it is already surrounded by a test to ensure that the key does not already exist. (as in your example)
That is why I'm asking if there is any way that it can get the 2 mixed up - or if there is some case in which it uses the Text as a Key if I do not specifically set a key.
One additional point - I only saw this problem one time on WindowsXP and that was back in the early development when I probably didn't check for the existance of the key first.My test engineer tells me it now happens frequently on Windows7 but he has never seen the problem on XP... so the same code seems to work differently on Win7. I know you have a different 'look' when I set it to Windows7 so do you do anything else differently?
I can't create a demo since I can't even make it fail myself.
What I need to know is why the error occurs during a Paint event rather than at the time I actually add the duplicate node.
Does this mean the node must be added in a Begin/EndUpdate block? (which maybe causes it to not check for duplicates until it resumes updating - and presumably painting)
If that is the case then I know where the error must be occuring since I only use a Begin/EndUpdate block in one location.That is the same location where I add a bunch of nodes without keys.
I have seen a number of entries in the forum where it states that all nodes in the Tree must have a unique key. However you have an Add() function without any parameters which I use to load multiple nodes that I do not even need to find by key. That seems to work fine ... but could that be what is causing the problem?
Do I need to generate a unique key for each node even if I never plan to use that key?(That seems to contradict what appears to work fine - but it might explain the problem.)
Hi Mike,
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.
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
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?
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)
The state of this issue is resolved it should be included in the upcoming Service release.
Thank you for using Infragistics Components.
Hi,
Has this issue been resolved? If so, is there an upgrade available?
I am struggling with the exact same problem.
I have created a support ticket for you with id CAS-84102-752GMV, in order to investigate this issue further for you.
That makes more sense. If it is displaying the 'ToString' value that would probably be the Text.I do add a node with that text to the Tree - but that is also the node where I check for its existance before adding it.
I dont know how there could be 2 UIElements pointing to it since the tree is never referenced from anywhere except the main thread. (The data loaded into this tree comes from small files on the local system so it loads very fast - no need to use threading.)
Hopefully the developers will agree with your assessment as I have now had reports from my Japanese localization team that they are also sometimes hitting the problem.
Thanks
I don't beleive there is any way to catch an exception like this. Once a control blows up during a paint operation, I don't know of any way to recover.
I took another look at the code where the exception is occurring and the caller always creates a new Hashtable before calling the method. So there's no way any nodes could exist in the table at the time the method is called.
The HashTable here is using the node itself as the key, not the Key or Text property of the node. So the message you are getting does not indicate that the problem is with the node's text, it's just showing you the ToString of the node in the error message.
What the code does is loop through the NodeUIElements in the tree and cache them so they can be re-used. So the only way I can see that you could possibly get this error is if you have two NodeUIElements in the tree that are both pointing to the same node. In theory, this should never happen, except in the case of a threading issue.
Having said that... since this is just a caching mechanism for efficiency, I don't see any real harm in us changing this code to avoid the exception. The worst-case scenario would be a slight performance hit, which is certainly preferable to an Exception. So I am going to ask Infragistics Developer Support to write this up and for developer review and we will see if we can get this corrected in the next service release.