Removing a balloon from a node

Walter,

I have programatically added GoBalloons to GoNodes within my Document for the purpose of telling the user that there is something "wrong" with a particular GoNode and should be fixed. Upon fixing the issues I would like the GoBallons removed from the document.
Unfortunately the code required to remove the GoBalloons does not seem to be as straightforward as the code used to add them.
Code to add GoBalloon:
Person p = FindPerson(NodeID);
PersonNode pn = pDoc.FindNode(p);
Northwoods.Go.GoBalloon comment = new Northwoods.Go.GoBalloon(); comment.Text = "Node #" + pn.Person.NodeID + " failed consistency check."; comment.Position = new PointF(pn.Position.X + 61, pn.Position.Y + 61);
pn.Add(comment);
Code to remove GoBalloon
foreach (GoObject obj in pDoc) { if (obj is GoBalloon) { GoBalloon comment = (GoBalloon)obj; pDoc.Remove(comment); }
}

Yes, that’s a restriction imposed by .NET collections – it’s not specific to GoDiagram: you are not allowed to modify a collection while iterating over it.

Just do the Remove outside of the loop.
Your code doesn't quite make sense to me, though: since you have added a GoBalloon as a child of a node (i.e. a GoGroup), iterating through the top-level objects of a GoDocument (if that is what your "pDoc" variable is) will never see those children -- it will only see the top-level nodes.
Only once you have a node can you iterate over its children to find a GoBalloon that you want to remove. And once you find it, you'll need to remove it outside of that iteration loop.

I actually got it to work -sort of.

I discovered that my GoBalloons were all hiding inside GoPoloygons. So first I iterated through all of the GoNodes then I iterated through all of the GoPolygons within each GoNode and finally I checked to see if there were any GoBalloons in the GoPolygons.
Here's the weird part. If I had, lets say 4 GoBalloons for each one of my GoNodes, when I iterate through the GoNode->GoPolygon collection to delete them, the first 3 are removed but the last one is not.

That also doesn’t make sense to me: GoPolygon is just a GoShape – it’s not a GoGroup, so it cannot contain any other GoObjects.

However, GoNode is a GoGroup, so you can easily Add and Remove and reorder GoObject as "children" of the group.
GoBalloon is also a GoGroup, and it contains a GoPolygon, but I hope that isn't what you are talking about.

This is my code to remove the GoBalloons.

private void ClearFailedNodeMessages() { foreach (GoObject obj in pDoc) { if (obj is PersonNode) { PersonNode pn = obj as PersonNode; PointF pt = new PointF(pn.Position.X + 61, pn.Position.Y + 61); if (pDoc.PickObject(pt, false) is GoPolygon) { GoPolygon poly = (GoPolygon)pDoc.PickObject(pt, false); if (poly.Parent is GoBalloon) { GoBalloon comment = (GoBalloon)poly.Parent; pDoc.Remove(comment); } } } } }
So I stand corrected. GoPolygon is a grandchild of PersonNode. It's parent is a GoBalloon. The weird thing is that when I tried to iterate through the PersonNodes and checked each GoObject to see if it was a GoBalloon, I would get errors telling me that I couldn't cast a GoPolygon as a GoBalloon.

You shouldn’t be using PickObject to find a child object – what if another unrelated object happened to be there, in front of that node?

Instead just iterate through the children of the node, looking for one (or more?) GoBalloons.

GoCollection found = new GoCollection(); foreach (GoObject obj in pDoc) { PersonNode pn = obj as PersonNode; if (pn == null) continue; foreach (GoObject child in pn) { GoBalloon ball = child as GoBalloon; if (ball != null) found.Add(ball); } } foreach (GoObject x in found) x.Remove();

That makes sense. I will give it a try and let you know what happens.