Dragging nodes in and out of a GoSubGraph


I am new to Northwoods.Go package. What I am trying to do is extending the GoSubGraph class to allow nodes drag into or out of the GoSubGraph. The Go version I am using is 2.6.2 for .NET WinForms.
If someone can point me the sample code that I can play with, that will be very helpful.
There was a sample with the functionalities I need. http://www.nwoods.com/forum/uploads/SubGraphApp.zip. But I cannot open this page.
Thanks advance for any help.

The SubGraphApp included in Samples allows dragging in & out when of subgraphs when you hold the shift key.

Thank you. I got it.



I have played with the SubGraphApp a little while; it is very helpful.
However is there any way to drag the nodes out of the SubGraph without hitting the "Shift" key? If it is possible, which methods should be overrided?
I have extended the GoSubGraph and overrided the OnSelectionDropped. Nodes can be dropped into the SubGraph. When they are in, they are stucked inside and cannot be dragged out of the SubGraph.

If you look at SubGraphDraggingTool in SubGraphApp, you see the line
if (MustBeMoving() && this.Selection.Primary != null) {
in DoDragging… and that’s where it does the drag in / drag out logic.
GoToolDragging.MustBeMoving() returns true if the Shift key is down.
so, if you add this override in SubGraphDraggingTool :
public override bool MustBeMoving() { return true; }
you get a SubGraphApp where everything is a forced move.

But, after playing with this a while... it "feels" awful. It's impossible to move nodes around inside a subgraph to "grow" the subgraph.
And a side effect is that GoView. DragsRealtime is turned off, which also hurts usability.
so... it's possible, I just don't recommend it. We'll investigate other possibilities for you.

If you use the BoxArea example class in Demo1 instead of GoSubGraph, you can get the effect you want pretty easily.

I have put up a modified version of BoxArea: http://www.nwoods.com/forum/uploads/BoxArea.cs. This also requires implementing a GoView.BackgroundSelectionDropped event handler, as shown in http://www.nwoods.com/forum/uploads/GraphView.cs. You can replace these two files in your 2.6.2 Demo1 sample directory.

This code works whether GoView.DragsRealtime is true or false.

It also allows the user to resize the BoxArea explicitly or to extend it a little bit to automatically include the GoView.Selection if, when the selection is dropped, it extends past (crosses over) the border.

The GoView.BackgroundSelectionDropped event handler handles the case of dragging something out of a BoxArea without dropping it into another BoxArea.

Thank you for investigating other possibilities for me and your quick response.
This is what we suppose to do.
  1. Dragging multiple selected nodes into a box. Still can drag box(es) with nodes in it(them) and drop into another box (very similar to subgraph in subgraph).
  2. Dragging entity inside box.
  3. Dragging entity out of the box.
  4. The layouts could be different inside box and outside of box.
From 1 and 4, since we really need features pretty much like the subgraphs in subgraph,0 I guess that GoSubGraph is the best choice for us. Is this correct? If the answer is 'Yes', I am stuck in GoSubGraph. Is there anyway to implement a state of draging, like create an enum { DragInside, DragCrossWall, DragOverlay,...}, than set the state that allows different types of draggings?

The BoxArea sample inherits from GoSubGraphBase. It doesn’t have support for collapse/expand or CollapsedObject, or the same model for defining the border. But if you need those features, you could implement them yourself in the BoxArea class


Thank you very much!


This modified BoxArea is ideal for an app im trying to create.
I have some questions:
1/ Is it possible for nodes to become a member of a box area when the box area is dragged around them?
2/ Is it possible to prevent the overlapping of boxareas? And is it possible to prevent boxareas containing other box areas?

Are you using Express or full GoDiagram?

I’m using the full version for this.

for #1, are you talking about resizing the BoxArea, or dragging it over some other objects?

same question for #2… dragging, resizing or both? Are you using a Grid?

This handles #2 for the dragging case, add this to the BoxArea class

// this DoMove prevents a BoxArea from being moved so that it intersects with another BoxArea.

public override void DoMove(GoView view, PointF origLoc, PointF newLoc) {

PointF pnt = ComputeMove(origLoc, newLoc);

// compute bounds if we were to move the box

RectangleF r = this.Bounds;

r.X = pnt.X;

r.Y = pnt.Y;

// pick any objects that intersect with this BoxArea

GoCollection picks = (GoCollection)view.Document.PickObjectsInRectangle(r, GoPickInRectangleStyle.SelectableOnlyIntersectsBounds, null, 999999);

foreach (GoObject o in picks) {

if (o is BoxArea && o != this) {

pnt = origLoc;




this.Location = pnt;


#1 Both if possible. I’d like to have the Box area in my palette, and when its dropped onto the document, if a node is inside, that node to become a member of the BoxArea. If the BoxArea is then resized to include another node, this should also be included.

#2 Again both, it would be great if I could prevent overlap as a result of dragging and resizing.
I'm not currently using a grid, but i'm not against it, if it makes life easier!
addition to your code for preventing overlap, i added this to the start of OnSelectionDropped in BoxArea class:
// this stops a BoxArea from being dragged into another BoxArea
foreach (GoObject obj in view.Selection)
if (obj is BoxArea && obj != this)
return false;

This handles drop from a palette and drop within a view, and adds the contained objects to BoxArea. (Note this is an extension of the existing BoxArea sample code for handling BackgroundSelectionDropped.

in your GoView class:

// Needed for BoxArea

protected override void OnBackgroundSelectionDropped(GoInputEventArgs evt) {

BoxArea box = this.Selection.Primary as BoxArea;

if (box != null && this.Selection.Count == 1) {

// pick any objects that are contained with this BoxArea

GoCollection within = (GoCollection)this.Document.PickObjectsInRectangle(box.Border.Bounds, GoPickInRectangleStyle.SelectableOnlyContained, null, 999999);

box.AddCollection(within, true);


else {

bool wasinbox = false;

foreach (GoObject obj in this.Selection) {

if (obj.Parent is BoxArea) {

wasinbox = true;




if (wasinbox) {

// add all selected objects as top-level objects in the DefaultLayer

this.Document.DefaultLayer.AddCollection(this.Selection, true);





Want to try the resizing code on your own? You should have enough of the flavor now…

oh… my OnBackgroundSelectionDropped code doesn’t avoid adding a BoxArea to a BoxArea. Just create a within2 collection and iterate within, adding all non-BoxArea objects to within2.

Thanks for all your help Jake,

I've implemented the resize functionality, with your code samples it was easy!
One small thing, sometimes, when I drag a BoxArea over a node, the OnBackgroundSelectionDropped function does not get called. Any ideas?