Grouping
Grouping in the RadDiagram is a way of organizing shapes and connections in logical groups. Groups are non-visual, logical collections of shapes and/or connections and/or other groups which can be created in code behind or with Commands.
Please note that the examples in this tutorial are showcasing Telerik Windows8 theme. In the Setting a Theme article you can find more information on how to set an application-wide theme.
Grouping API
IGroup, IShape and IConnection implement the IGroupable interface.
IGroup provides a collection of IGroupable Items. This practically means that you can have groups of shapes, connections and other groups. This allows you to have unlimited levels of nested logical groups.
The IGroupable interface has two members:
ParentGroup - of type IGroup.
ParentGroupChanged event- of type EventHandler
>.
The IGroup has the following members
IsSelected- of type boolean.
Items - IList
. Name - string.
ItemsChanged - of type NotifyCollectionChangedEventHandler.
SelectionChanged - of type EventHandler.
The RadDiagram provides the following "grouping" members:
Group([string groupName], params IGroupable[] items)) - creates an IGroup from a given Array of IGroupable items.
Ungroup(params IGroup[] items)- removes the logical groups previously created.
Groups - IEnumerable
. The list of root-level Groups created in the RadDiagram. GroupsChanged - of type EventHandler. Fires when grouping or ungrouping is performed. Does not fire when an Item's ParentGroup is changed.
GroupStyle - Style that applies to the Selection Rectangle around the logical groups.
The DiagramCommands class has Group and Ungroup which are both RoutedUICommands. The Group Command groups the selected IGroupable-s and the Ungroup command ungroups the selected IGroups.
Grouping In Code Behind
In the next example we will create 20 shapes with contents - "1", "2",... "20" and we will group them by their parity.
Let's first create some random shapes:
private void RadButton_Click_1(object sender, RoutedEventArgs e)
{
for (int i = 1; i < 21; i++)
{
RadDiagramShape shape = new RadDiagramShape() { Width = 30, Height = 30, Content = i };
shape.Geometry = ShapeFactory.GetShapeGeometry(CommonShapeType.EllipseShape);
shape.Position = new Point(random.Next(0, 900), random.Next(0, 200));
this.diagram.Items.Add(shape);
}
}
Private Sub RadButton_Click_1(sender As Object, e As RoutedEventArgs)
For i As Integer = 1 To 20
Dim shape As New RadDiagramShape() With {
.Width = 30,
.Height = 30,
.Content = i
}
shape.Geometry = ShapeFactory.GetShapeGeometry(CommonShapeType.EllipseShape)
shape.Position = New Point(random.Next(0, 900), random.Next(0, 200))
Me.diagram.Items.Add(shape)
Next
End Sub
Now let's implement some grouping logic on Button's Click:
private void RadButton_Click_3(object sender, RoutedEventArgs e)
{
IShape[] evenShapes = this.diagram.Shapes.Where(x => int.Parse(x.Content.ToString()) % 2 == 0).ToArray<IShape>();
IShape[] oddShapes = this.diagram.Shapes.Where(x => int.Parse(x.Content.ToString()) % 2 == 1).ToArray<IShape>();
this.diagram.Group("Even", evenShapes);
this.diagram.Group("Odd", oddShapes);
}
Private Sub RadButton_Click_3(sender As Object, e As RoutedEventArgs)
Dim evenShapes As IShape() = Me.diagram.Shapes.Where(Function(x) Integer.Parse(x.Content.ToString()) Mod 2 = 0).ToArray(Of IShape)()
Dim oddShapes As IShape() = Me.diagram.Shapes.Where(Function(x) Integer.Parse(x.Content.ToString()) Mod 2 = 1).ToArray(Of IShape)()
Me.diagram.Group("Even", evenShapes)
Me.diagram.Group("Odd", oddShapes)
End Sub
Below you can see how the grouping works:
Now let's play with grouping and upgrouping. Below are some code examples and the result of the code execution:
this.diagram.Group("123", this.diagram.Shapes[1], this.diagram.Shapes[2], this.diagram.Shapes[3]);
this.diagram.Group("345", this.diagram.Shapes[3], this.diagram.Shapes[4], this.diagram.Shapes[5]);
Me.diagram.Group("123", this.diagram.Shapes[1], this.diagram.Shapes[2], this.diagram.Shapes[3]);
Me.diagram.Group("345", this.diagram.Shapes[3], this.diagram.Shapes[4], this.diagram.Shapes[5]);
This makes group "123" with items {Shapes[1],Shapes[2]} and "345" with items {Shapes[3], Shapes[4], Shapes[5]}.
The creation of the second group excludes Shapes[3] from group "123".
Alternatively if we use one name in the method:
this.diagram.Group("123", this.diagram.Shapes[1], this.diagram.Shapes[2], this.diagram.Shapes[3]);
this.diagram.Group("123", this.diagram.Shapes[3], this.diagram.Shapes[4], this.diagram.Shapes[5]);
Me.diagram.Group("123", this.diagram.Shapes[1], this.diagram.Shapes[2], this.diagram.Shapes[3]);
Me.diagram.Group("123", this.diagram.Shapes[3], this.diagram.Shapes[4], this.diagram.Shapes[5]);
This produces a single group "123" with the 5 elements Shapes[1]-Shapes[5].
How To Create SubGroups
Subgrouping must be done from subgroups to parentgroups. In other words, creating a parent group, then creating its subgroup is not possible.
Below is an example of creating a subgroups and a parent group.
var groupA = this.diagram.Group("1-2", this.diagram.Shapes[1], this.diagram.Shapes[2]);
var groupB = this.diagram.Group("3-4", this.diagram.Shapes[3], this.diagram.Shapes[4]);
var parentGroup = this.diagram.Group("1-2-3-4",groupA,groupB);
Dim groupA = Me.diagram.Group("1-2", Me.diagram.Shapes(1), Me.diagram.Shapes(2))
Dim groupB = Me.diagram.Group("3-4", Me.diagram.Shapes(3), Me.diagram.Shapes(4))
Dim parentGroup = Me.diagram.Group("1-2-3-4", groupA, groupB)
In the picture below you can see a how consecutive clicks on a shape reflects the selection of groups.
First click selects the outermost (the biggest group), second click selects the smaller group and the third selects only the shape.The forth click will select the biggest group and so on.
If you need to select particular items without selecting the whole group, you can use Rectangular Selection.
What will happen if we try to create parent group then create subgroups?
this.diagram.Group("1-2-3-4", this.diagram.Shapes[1], this.diagram.Shapes[2], this.diagram.Shapes[3], this.diagram.Shapes[4]);
this.diagram.Group("1-2", this.diagram.Shapes[1], this.diagram.Shapes[2]);
Me.diagram.Group("1-2-3-4", this.diagram.Shapes[1], this.diagram.Shapes[2], this.diagram.Shapes[3], this.diagram.Shapes[4]);
Me.diagram.Group("1-2", this.diagram.Shapes[1], this.diagram.Shapes[2]);
This will create two separate groups - "1-2-3-4" with items {Shapes[3], Shapes[4]} and "1-2" with items {Shapes[1], Shapes[2]}.
Creating a parent group then creating its subgroup is not possible.
Ungrouping
You can Ungroup one or several groups with the Ungroup method of RadDiagram:
this.diagram.Ungroup(groupA, groupB, groupC);
this.diagram.Ungroup(this.diagram.Groups.ToArray());
Me.diagram.Ungroup(groupA, groupB, groupC);
Me.diagram.Ungroup(this.diagram.Groups.ToArray());
Grouping With Commands
Using the DiagramCommands Group and Ungroup is straightforward. Group applies to the selected IGroupables and Ungroup applies to the selected IGroups.
<telerik:RadDiagram IsSnapToItemsEnabled="False" x:Name="diagram" HorizontalAlignment="Stretch" Height="200" Width="800"
IsBackgroundSurfaceVisible="True" />
<telerik:RadButton Command="telerik:DiagramCommands.Group"
CommandTarget="{Binding ElementName=diagram}" Content="Group" />
<telerik:RadButton Command="telerik:DiagramCommands.Ungroup"
CommandTarget="{Binding ElementName=diagram}" Content="Ungroup" />