Hi. I have a problem dropping SubGraph from one GoView to another.
I need to store a collection of ID’s of my node in my subgraph, so I’ve created descendant on needed Go classes:
public class MyNode: GoBasicNode {
private string _id;
public MyNode():base() {
_id = Guid.NewGuid().ToString(“N”);
this.DragsNode = true;
}
public string Id {
get{ return _id; }
}
}
public class MySubGraph: GoSubGraph {
private Hashtable _ids = new Hashtable();
public MySubGraph():base() {
}
public override void Add(GoObject obj) {
MyNode node = obj as MyNode;
if(node != null) {
_ids.Add(node.Id, node);
base.Add (obj);
}
}
public override void Remove(GoObject obj) {
MyNode node = obj as MyNode;
if(node != null) {
_ids.Remove(node.Id);
base.Remove (obj);
}
}
public override void Clear() {
_ids.Clear();
base.Clear ();
}
}
Than I’ve added 2 GoView on a form and added objects to first of them:
MyNode node1 = new MyNode();
node1.Text = “MyNode 1”;
node1.Position = new PointF(10f,10f);
_view1.Document.Layers.Default.Add(node1);
MyNode node2 = new MyNode();
node2.Text = “MyNode 2”;
MySubGraph subGraph = new MySubGraph();
subGraph.Add(node2);
subGraph.Position = new PointF(100f, 10f);
_view1.Document.Layers.Default.Add(subGraph);
Now, first node can be dragged to second view easily. But the second node(inside SubGraph)… trying to drag second node to second view throws an exception:
OnDragDrop: System.ArgumentException: Item has already been added. Key in dictionary: “125ff586eb544fac8e5abd922627eb16” Key being added: “125ff586eb544fac8e5abd922627eb16”
at System.Collections.Hashtable.Insert(Object key, Object nvalue, Boolean add)
at System.Collections.Hashtable.Add(Object key, Object value)
at GoSubGraphCopyTest.MySubGraph.Add(GoObject obj) in d:…\visual studio projects\testsandsamples\gosubgraphcopytest\form1.cs:line 119
at Northwoods.Go.GoSubGraph.CopyChildren(GoGroup newgroup, GoCopyDictionary env)
at Northwoods.Go.GoGroup.CopyObject(GoCopyDictionary env)
at Northwoods.Go.GoNode.CopyObject(GoCopyDictionary env)
at Northwoods.Go.GoCopyDictionary.Copy(GoObject obj)
at Northwoods.Go.GoDocument.CopyFromCollection(IGoCollection coll, Boolean copyableOnly, Boolean dragging, SizeF offset, GoCopyDictionary env)
at Northwoods.Go.GoView.DoExternalDrop(DragEventArgs evt)
at Northwoods.Go.GoView.OnDragDrop(DragEventArgs evt)
It seems that somewhere (in GoGroup.CopyObject or GoSubGraph.CopyChildren) the GoGroup internal object collection is cleared without using public o virtual method or something like this.
What can i do make my SubGraph able for dropping???
If I understand your situation, I think you should override GoSubGraph.CopyObject to set _ids to a new HashTable().
The general idea is that if you add state to your objects, you need to handle what happens when you copy them, or add or remove things from them. You probably have a similar problem with MyNode._id.
Thanks for advise. It looks like overriding CopyObjects should help.
But I thought that CopyObjects should use GoSubGraph API to manipulate its internals… In my CopyObjects override I’d better use this.Clear() method instead of _ids = new Hahstable().
About MyNode._id… I can’t explain why, but It copies itself without any problems. If I set in first view MyNode._id = “blabla” then just drug and drop it to the second view the _id of MyNode in second view will still be “blabla”.
No, the copied object will have a reference to the same Hashtable as the original object, so Clear()'ing that will just lose whatever information you had in the original object.
For unshared references, you really need to reinitialize by creating a new object (Hashtable in this case), and copying the information that that object contains.
That’s right–the String reference is copied, but I was assuming you wanted those _id values to be unique within the document, which means you need to update them in your override of CopyObject.
See the section about Copying in the User Guide, page 44.
Hmmm… I think I begin to understand the general idea of adding my own state to objects. Thanks again!
My be you can help me with my next problem?
I have a class, that inherit from GoIconicNode. I want to add a second icon to it, which position will be relative to the original icon.
I’ve created private varible of type GoImage, initialise it in constructor like this:
_pinIcon = new GoImage();
_pinIcon.Selectable = false;
_pinIcon.DragsNode = true;
_pinIcon.Image = _defaultPinIcon;
this.Add(_pinIcon);
And override the LayoutChildren method:
public override void LayoutChildren(GoObject childchanged) {
if(base.Initializing)
return;
if((_pinIcon != null) && (this.Icon != null)){
RectangleF r = this.Icon.Bounds;
_pinIcon.Top = r.Top;
_pinIcon.Left = r.Left;
}
base.LayoutChildren (childchanged);
}
If I try to layout this nodes using GoLayoutForceDirected, my _pinIcon appears in strange(and wrong) positions. What did I miss?
Oooops… sorry…
The last question in not actual any more - I’ve found bug in my code