Class Group

GoDiagram®
v10.0.8
by Northwoods Software®

A Group is a Node that can contain a subgraph of Nodes and Links, which are members of the group.

Inheritance
Group
Namespace: Northwoods.Go
Assembly: Northwoods.GoDiagram.WinForms.dll
Syntax
public class Group : Node, IHasContextMenu, IHasToolTip
Remarks

For more discussion, see Introduction to Groups. See samples that make use of Groups in the samples index.

Although you can create a Group and Add(Part) it to a Diagram, this does not update the Model. It is more common to create a group by adding a node data object to the model by calling AddNodeData(TNodeData). For example:

myDiagram.StartTransaction("make new group");
myDiagram.Model.AddNodeData(new MyNodeData { Key = "Omega", IsGroup = true });
myDiagram.CommitTransaction("make new group");

This will cause a Group to be created (copying the template found in GroupTemplateMap), added to the Diagram in some Layer (based on LayerName), and bound to the group data (resulting in Data referring to that group data object). Note that the object includes setting IsGroup to true, to indicate that the object represents a Group rather than a regular Node or simple Part.

The member Parts of a Group, which you can access as the MemberParts collection, belong to the group but are not in the visual tree of the group. All Parts are directly in Layers -- they cannot be inside a Panel. This allows group member parts to be in layers different from the group's layer.

You can change the membership of a Node or a simple Part in a Group by setting its ContainingGroup property. This is done automatically for you by the diagram if you initialize the group property on the node data in the model to be the key of the containing group node data. Thus you should do something like:

myDiagram.StartTransaction("add new member");
myDiagram.Model.AddNodeData(new MyNodeData { Group = someExistingGroupKey, ... });
myDiagram.CommitTransaction("add new member");

where you would make sure the node data object included all of the properties you need. You can also change the relationship dynamically by calling SetGroupKeyForNodeData(TNodeData, TNodeKey).

The membership of Links is computed automatically for you by the diagram based on the membership of the connected Nodes. For example, if the FromNode is a top-level node but the ToNode is a member of a group, the link is a top-level link. If the two connected nodes both belong to the same group, the link is a member of that group. If the two connected nodes belong to different groups, the link belongs to the common container group, if there is any. Note that if a link connects a member of a group with the group itself, the link is a member of that group.

All of the group-member relationships effectively form a tree structure. These properties and methods are useful in navigating these relationships:

As the membership of a group changes, you may want to update the appearance of the group. You can set the MemberAdded property to be an Action that is called. These functions must not modify any membership relationships -- these function properties just exist to update the appearance of the Group.

You can control whether certain Nodes are added to a Group by GroupSelection() or AddMembers(IEnumerable<Part>, bool) or AddTopLevelParts(IEnumerable<Part>, bool) by affecting the result of IsValidMember(Group, Part), which is responsible for deciding whether it is OK to add a Node to a Group or to remove a Node from a Group to be a top-level node. You can override that predicate on CommandHandler, but it is easier to set the MemberValidation or MemberValidation functional property.

For a more general discussion of validation, see Introduction to Validation.

The area occupied by the subgraph is represented in the group's visual tree by a Placeholder. As the group Placeholder grows and shrinks based on the sizes and positions of the member nodes and links, the group will grow and shrink accordingly. The placeholder is always the LocationElement, although you may specify any Spot as the LocationSpot. A Group need not have a placeholder, but it may have at most one.

A group has its own Layout property that is used to position the member nodes and route the member links.

The Group class also supports the notion of expanding and collapsing the subgraph, causing the member nodes and links to be shown or hidden. Principally this is a matter of setting IsSubGraphExpanded. Changes to this property will result in calls to CollapseSubGraph() or ExpandSubGraph(), as appropriate.

If you want to change the appearance of the group you can do so in a function that you assign to the SubGraphExpandedChanged property. This function must not modify any member relationships or expand or collapse any groups -- the functional property just exists to update the appearance of the Group.

For more discussion and examples, see SubGraphs.

If you want the user to be able to create a Group out of the currently selected Parts using the GroupSelection() command, you need to first set the ArchetypeGroupData property to a data object with IsGroup set to true. If you want the user to be able to ungroup a Group, using the UngroupSelection(Group) command, you need to set Ungroupable to true.

For more discussion and examples, see Groups, SubGraphs, and Sized Groups.

Only Groups that are in Diagrams can have member Parts or connections via Links. Templates should not be connected with Links, be labels of Links, be members of Groups, have any member Parts, or have any Adornments.

Constructors

Group()

Constructs an empty Group with no visual elements and no member parts; normally a Group will have some visual elements surrounding a Placeholder.

Declaration
public Group()
Remarks

The default Panel type is PanelLayoutPosition.

Group(PanelLayout)

Constructs an empty Group with no visual elements and no member parts; normally a Group will have some visual elements surrounding a Placeholder.

Declaration
public Group(PanelLayout type)
Parameters
Type Name Description
PanelLayout type

if null, the default Panel type is PanelLayoutPosition.

Group(string)

Constructs an empty Group with no visual elements and no member parts; normally a Group will have some visual elements surrounding a Placeholder.

Declaration
public Group(string type)
Parameters
Type Name Description
string type

if the empty string, the default Panel type is PanelLayoutPosition.

Properties

ComputesBoundsAfterDrag

Gets or sets whether the size of the area of the Group's Placeholder should remain the same during a DraggingTool move until a drop occurs.

Declaration
public bool ComputesBoundsAfterDrag { get; set; }
Property Value
Type Description
bool
Remarks

Groups within temporary layers (such as new Groups during a drag-copy) are unaffected by this property.

In other words, when the value is true, re-computing the bounds of the members is suspended until a drop occurs, at which time the border is recomputed, perhaps not including some members that had been dragged out and reparented. The default value is false.

Gets or sets whether a Placeholder's bounds includes the bounds of member Links.

Declaration
public bool ComputesBoundsIncludingLinks { get; set; }
Property Value
Type Description
bool

The default value is true. If this is false, only non-Link member Parts are used to compute the Placeholder's bounds in document coordinates.

ComputesBoundsIncludingLocation

Gets or sets whether a Placeholder's bounds includes the previous Group.Location.

Declaration
public bool ComputesBoundsIncludingLocation { get; set; }
Property Value
Type Description
bool
Remarks

The default value is false.

HandlesDragDropForMembers

Gets or sets whether drag-and-drop events may be bubbled up to this Group if not handled by member Parts.

Declaration
public bool HandlesDragDropForMembers { get; set; }
Property Value
Type Description
bool
Remarks

The default value is false -- each Node or Link that is a member of the Group needs to define its own MouseDragEnter, MouseDragLeave, and MouseDrop event handlers if you want dragging/dropping on a member part to act as if the user were acting on the group.

This is currently restricted to only call the mouseDragEnter, mouseDragLeave, and mouseDrop event handlers defined on the whole Group, not on any element inside the Group's visual tree.

IsSubGraphExpanded

Gets or sets whether the subgraph contained by this group is expanded.

Declaration
public bool IsSubGraphExpanded { get; set; }
Property Value
Type Description
bool
Remarks

Changing this property's value will call CollapseSubGraph() or ExpandSubGraph(), and also will call the value of SubGraphExpandedChanged if it is a function.

The default value is true -- this group's member parts are shown.

There is an analogous property for expanded/collapsed trees of Nodes and Links: IsTreeExpanded.

Layout

Gets or sets the Layout used to position all of the immediate member nodes and links in this group.

Declaration
public Layout Layout { get; set; }
Property Value
Type Description
Layout
Remarks

By default this property is an instance of Layout -- no special layout is used, which just makes sure each member node has a valid location.

A group layout must not be shared with any Layout.

MemberAdded

Gets or sets the function that is called after a member Part has been added to or removed from this Group.

Declaration
public Action<Group, Part, bool> MemberAdded { get; set; }
Property Value
Type Description
Action<Group, Part, bool>
Remarks

It is typically used to modify the appearance of the group. The first argument will be this Group. The second argument will be a Part, typically a Node, but may be a simple Part or a Link. The third argument will be a bool, true if a member was added, and false if it was removed.

If the value is a function, that function must not modify any membership relationships. The member Part has already been added -- trying to remove it or adding or removing another member or the Group itself may produce undefined behavior.

The default value is null -- no function is called.

MemberParts

This read-only property returns an iterator over the member Parts of this Group.

Declaration
public IReadOnlyCollection<Part> MemberParts { get; }
Property Value
Type Description
IReadOnlyCollection<Part>
Remarks

Setting ContainingGroup to refer to this Group will add that part to this collection. The Parts can be Nodes, Links, Groups, or simple Parts.

A template should not have any member parts.

MemberValidation

Gets or sets the predicate that determines whether or not a Part may become a member of this group.

Declaration
public Func<Group, Part, bool> MemberValidation { get; set; }
Property Value
Type Description
Func<Group, Part, bool>
Remarks

If this is non-null, the predicate is called in addition to any MemberValidation predicate.

The default predicate is null, which is equivalent to simply returning true. The first argument will be this Group. The second argument will be a Part, typically a Node, but will not be a Link or an Adornment.

The function, if supplied, must not have any side-effects.

Placeholder

This read-only property returns a Placeholder that this group may contain in its visual tree.

Declaration
public Placeholder Placeholder { get; }
Property Value
Type Description
Placeholder

SubGraphExpandedChanged

Gets or sets the function that is called when IsSubGraphExpanded has changed value.

Declaration
public Action<Group> SubGraphExpandedChanged { get; set; }
Property Value
Type Description
Action<Group>
Remarks

The argument to that function will be this Group.

If the value is a function, that function must not expand or collapse any groups. The Group has already been expanded or collapsed -- trying to change it again may produce undefined behavior.

The default value is null -- no function is called.

Ungroupable

Gets or sets whether the user may ungroup this group.

Declaration
public bool Ungroupable { get; set; }
Property Value
Type Description
bool
Remarks

The default value is false.

See Also

WasSubGraphExpanded

Gets or sets whether the subgraph starting at this group had been collapsed by a call to ExpandSubGraph() on the containing Group.

Declaration
public bool WasSubGraphExpanded { get; set; }
Property Value
Type Description
bool
Remarks

The default value is false.

See Also

Methods

AddMembers(IEnumerable<Part>, bool)

Add the Parts in the given collection as members of this Group for those Parts for which IsValidMember(Group, Part) returns true.

Declaration
public bool AddMembers(IEnumerable<Part> coll, bool check = false)
Parameters
Type Name Description
IEnumerable<Part> coll
bool check

whether to call IsValidMember(Group, Part) to confirm that it is valid to add the Part to be a member of this Group.

Returns
Type Description
bool

true if all non-Links were added to this Group; false if some Parts or Nodes were not able to be added.

Remarks

If the check argument to this method is not supplied or false, this will set ContainingGroup on each part unconditionally, not calling IsValidMember(Group, Part).

The CommandHandler predicate will use MemberValidation and MemberValidation, if either or both are defined.

At this time there is no "RemoveMembers" method. If you want to make a collection of Parts to be top-level parts, not members of any Group but still in the Diagram, call AddTopLevelParts(IEnumerable<Part>, bool). If you want to remove a collection of Parts not only from a Group but from the whole Diagram, call RemoveParts(IEnumerable<Part>, bool).

CanAddMembers(IEnumerable<Part>)

See if the given collection of Parts contains non-Links all for which IsValidMember(Group, Part) returns true.

Declaration
public bool CanAddMembers(IEnumerable<Part> coll)
Parameters
Type Name Description
IEnumerable<Part> coll
Returns
Type Description
bool
Remarks

The CommandHandler predicate will use MemberValidation and MemberValidation, if either or both are defined.

This does not check IsReadOnly or IsReadOnly, but commands and tools should check those properties.

CanUngroup()

This predicate returns true if Ungroupable is true, if the layer's AllowUngroup is true, and if the diagram's AllowUngroup is true.

Declaration
public bool CanUngroup()
Returns
Type Description
bool

true if the user may ungroup this object.

Remarks

This does not check IsReadOnly or IsReadOnly, but commands and tools should check those properties.

CollapseSubGraph()

Hide each of the member nodes and links of this group, and recursively collapse any member groups.

Declaration
public void CollapseSubGraph()
Remarks

This changes the value of IsVisible() of the whole subgraph and the parts owned by those member nodes and links. However, this group's visibility is unchanged.

This sets IsSubGraphExpanded to false on this group and on all of the nested Groups. For those nested Groups that were expanded, WasSubGraphExpanded is set to true.

This method does not perform a transaction or start any animation.

To collapse trees made of Nodes and Links, use CollapseTree(int).

EnsureBounds()

Measures if needed to make sure the MeasuredBounds and NaturalBounds are all real numbers, primarily to get the actual width and height.

Declaration
public override void EnsureBounds()
Overrides
Remarks

ActualBounds will get a real width and height, but the x and y values may continue to be NaN if they were that way beforehand.

This is sometimes necessary to call when defining custom layouts or implementing virtualization, so that it can work with the actual size of the nodes.

For efficiency, do not call this method unnecessarily.

ExpandSubGraph()

Show each member node and link, and perhaps recursively expand nested subgraphs.

Declaration
public void ExpandSubGraph()
Remarks

This may change the value of IsVisible() of the whole subgraph and the parts owned by those member nodes and links. However, this group's visibility is unchanged.

This sets IsSubGraphExpanded to true on this group and on all of the nested Groups. This will expand a nested group only if its WasSubGraphExpanded property was true.

This method does not perform a transaction or start any animation.

To expand trees made of Nodes and Links, use ExpandTree(int).

FindExternalLinksConnected()

Returns an enumerable of the Links that connect with this group or any node contained by this group, in either direction, but that are not internal to this group.

Declaration
public IEnumerable<Link> FindExternalLinksConnected()
Returns
Type Description
IEnumerable<Link>
Remarks

Links that are contained by this group (even in nested groups) are not included in the result collection.

See Also

FindExternalNodesConnected()

Returns an iterator over all of the Nodes that are connected with this group or any node contained by this group, by a link in either direction, but that are not internal to this group.

Declaration
public IEnumerable<Node> FindExternalNodesConnected()
Returns
Type Description
IEnumerable<Node>
Remarks

Nodes that are contained by this group (even in nested groups) are not included in the result collection. However this group itself might be in the results if there is a reflexive link connected to this group.

See Also

FindSubGraphParts()

Return a collection of Parts that are all of the nodes and links that are members of this group, including inside nested groups, but excluding this group itself.

Declaration
public IEnumerable<Part> FindSubGraphParts()
Returns
Type Description
IEnumerable<Part>
Remarks

For member nodes that are Groups, this will include its members recursively.

If you want only the immediate members of this group, use the MemberParts property.

If you want to find the collection of Nodes and Links that are in the subtree of a given Node, use FindTreeParts(int).

Move(Point, bool)

Move this Group and all of its member parts, recursively.

Declaration
public override void Move(Point newpos, bool useLocation = false)
Parameters
Type Name Description
Point newpos

a new Point in document coordinates.

bool useLocation

true if you want to set the Location instead of the position. False by default.

Overrides

Implements