How can I create a process node that has multiple sub-graphs or groups?

I apologize for what seems like my newbie question, but I am having trouble constructing a node that has different distinct sections. I have tried to use pieces from the grouping, navigator, swimlanes and the plannogram samples, but I cannot seem to get the pieces in the right place. My problem essentially is how do I define in the xaml where the groups are going to be and how do I set the name of the group such that I can set the group key on the nodes? The xaml I have now for this node looks like this:

   <DataTemplate DataType="{x:Type proj:vmPSNode}">
        <Border BorderBrush="Black" BorderThickness="1,0,1,0" MinWidth="300" MinHeight="250" CornerRadius="5">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="30" />
                    <RowDefinition Height="*" />
                    <RowDefinition Height="30" />
                </Grid.RowDefinitions>
                <Border BorderBrush="Black" BorderThickness="0,1,0,1" HorizontalAlignment="Stretch" CornerRadius="3" Background="LightGray">
                    <DockPanel>
                        <Image Source="{StaticResource Hadoop_PS}" Height="28" DockPanel.Dock="Right" Margin="3,0" />
                        <!-- Need a subgraph here!!! -->
                        <StackPanel />
                    </DockPanel>
                </Border>
                
                <!-- Need a subgraph here!!! -->
                <StackPanel Grid.Row="1" />

                <Border Grid.Row="2" BorderBrush="Black" BorderThickness="0,1,0,1" HorizontalAlignment="Stretch" CornerRadius="3" Background="LightGray">
                    <!-- Need a subgraph here!!! -->
                    <StackPanel />
                </Border>

            </Grid>
        </Border>
    </DataTemplate>`

I was hoping that you could give me a start on how to get a node with three distinct subgraphs put together. I have attached an image of how this looks when using the GO Diagram tools for Windows Forms.

Each Group should have its own Group.Layout. If you include a GroupPanel that will represent where the subgraph will be relative to the elements of the Group.

You may need to customize a layout in order to position the input ports and the output ports the way that you want. Or perhaps you want to arrange the ports yourself (in a row above the GroupPanel and in a row below the GroupPanel) and let the member Nodes and Links be positioned manually by the user – no Group.Layout would be needed then.

Walter,

Thank you for taking the time to respond and your answer is excellent but a bit further down the road from where I am having a problem.

I am confused on how I can even use the GroupPanel to load the nodes in there. How can I associate a group that would be placed there with the nodes that belong inside the group. Based on the examples I think that I need to set Key of the group, and then set the GraphSubKey on the Nodes that belong inside, but I cannot seem to set the Key of the group (or GroupPanel).

For instance if I do:

                <Border BorderBrush="Black" BorderThickness="0,1,0,1" HorizontalAlignment="Stretch" CornerRadius="3" Background="LightGray">
                    <DockPanel>
                        <Image Source="{StaticResource Hadoop_PS}" Height="28" DockPanel.Dock="Right" Margin="3,0" />
                        <!-- Need a subgraph here!!! -->
                        <go:GroupPanel Name="{Binding InputGroupName}"  /><!-- Not legal!!! -->
                        <go:GroupPanel Key="{Binding InputGroupName}"  /><!-- Not Valid!!! -->

                    </DockPanel>
                </Border>

A Group template can have at most one GroupPanel in it.

When setting up the model, you will want to have an object represented by a Group (by setting GoXam for WPF 2.2.4 to true) whose key you assign as the containing group key on the objects represented by Nodes. If you are using the GraphLinksModelNodeData class, you will want to set GoXam for WPF 2.2.4

Walter,

I guess I am not being clear on what I am asking. Let me try and break down my problems into simple questions.

I have modified the swim lanes example which gets me pretty close to what I want, and I can ask some simple questions.

Here is the XAML

<UserControl x:Class="SwimLanes.SwimLanes"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:go="http://schemas.nwoods.com/GoXam"
    xmlns:local="clr-namespace:SwimLanes">

    <UserControl.Resources>
        <DataTemplate x:Key="NodeTemplate">
            <go:NodePanel 
                go:Part.SelectionAdorned="True" 
                go:Part.Movable="True"
                go:Part.Selectable="True"
                go:Node.LocationElementName="border"
                go:Node.LocationSpot="TopLeft"
                go:Node.Location="{Binding Path=Data.Location, Mode=TwoWay}">
                <Border x:Name="border" Background="Purple" CornerRadius="3" Width="50" Height="50">
                    <TextBlock Text="A node" HorizontalAlignment="Center" VerticalAlignment="Center" />
                </Border>
            </go:NodePanel>
        </DataTemplate>
        <DataTemplate x:Key="GroupTemplate">
            <Border BorderBrush="Red" BorderThickness="2" MinWidth="300" Padding="0" Margin="0"
                    Background="Gray"
                    go:Node.LocationElementName="myGroupPanel"
                    go:Node.LocationSpot="TopLeft"
                    go:Node.Location="{Binding Path=Data.Location, Mode=TwoWay}"
                    go:Part.Movable="{Binding Data.CanMove.}"
                    go:Part.Selectable="True">
                <go:GroupPanel x:Name="myGroupPanel"  />
            <!--<go:Group.Layout>
                    <local:VerticalLayout Conditions="Standard GroupSizeChanged" />
                </go:Group.Layout>-->
            </Border>
        </DataTemplate>
    </UserControl.Resources>

    <Grid>
        <go:Diagram x:Name="myDiagram" 
                    NodeTemplate="{StaticResource NodeTemplate}" 
                    GroupTemplate="{StaticResource GroupTemplate}"
                    VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
                    >
        </go:Diagram>
    </Grid>
</UserControl>

Here is the code that I am working with:

namespace SwimLanes
{
    public partial class SwimLanes : UserControl
    {
        public SwimLanes()
        {
            InitializeComponent();

            var model = new GraphModel<SimpleData, String>();
            var nodes = new ObservableCollection<SimpleData>();

            for (int i=0; i<2; i++)
            {
                string root_node_key = "Root" + i;
                var root_node = new SimpleData() { Key = "Root" + i, IsSubGraph = true, Location = new Point(i*300, 0) };
                nodes.Add(root_node);

                //Create 3 groups per root node
                for (int j = 0; j < 3; j++)
                {
                    SimpleData group = new SimpleData() { CanMove = false };
                    group.Key = "Group " + nodes.Count();
                    group.IsSubGraph = true;
                    group.SubGraphKey = root_node_key;
                    group.Location = new Point(0, j * 100);
                    nodes.Add(group);

                    SimpleData node = new SimpleData();
                    node.Key = "Node " + nodes.Count();
                    node.SubGraphKey = group.Key;
                    nodes.Add(node);
                }
            }

            model.NodesSource = nodes;
            model.Modifiable = true;
            myDiagram.Model = model;
        }
    }

    public class SimpleData : GraphModelNodeData<String>
    {
        public SimpleData() { CanMove = true; }

        public bool CanMove { get; set; }
    }
}

Question 1: What is causing the padding between the outer group and in the inner groups?

Question 2: How come when I drag ‘A node’ it moves the entire group even though the group is not moveable (how come it does not move the node inside the group)?

Question 3: Why isn’t the positioning of the innner groups correct, when clearly I am setting a yposition ( group.Location = new Point(0, j * 100)), but it decides to just move it in the X anyway

Question 4: Why isn’t the positioning of the outer groups correct, when clearly I am setting a xpostion ( Location = new Point(i*300, 0) ), but it decides to just move it in the Y anyway

Thank for your time, and sorry I have not been more clear earlier.

  1. I believe that gap is caused by the GroupPanel.Padding having a default Thickness of 5.

  2. The Group template is using a GroupPanel, so by definition the location and size of the group will be determined by the bounds of its member nodes. So if there is only one member node, moving it will necessarily move its containing group.

3 & 4. Setting Group.Location will only move the Group, not its member Nodes. You can call Group.Move to both move a Group and all of its member Nodes. In your case, because your group template includes a GroupPanel, setting/binding the Group.Location has no effect because its GroupPanel determines the group’s location.

Note that you can modify a Group’s Location when it does not have a GroupPanel, as demonstrated in the Planogram sample.