Diagram with Group Layout

Hello,
I’m trying to set Group Location inside a group (overriding DoLayout()) programmatically.
All Groups may contains themselves more Groups .

When Groups are expanded is first called the layout DoLayout() of the children and then there from the parent.
Problem is that I’m not able to have parent Group where it should be,

Should I use ArrangementOrigin to set Groups Location inside the Layout?
if yes how to set/get correctly the Layout ArrangementOrigin properties of the group as the template contains more Visual element stacked ? Is there an easy way to get the layout Location inside the template? How to makes Group inside a layout group moved with their parent when DoLayout from the parent is called?

Thanks,

JJ

The location of any Node, including any Group, is determined by the layout that is responsible for positioning the node. For a top-level Group, that would be the Diagram.Layout; for a nested Group that would be the containing Group’s Group.Layout.

Hi Walter,

This is Ok but what about layout inside another Layout. When I set Location of Node inside a children Layout, which value should I take as ArrangementOrigin (for all different Layout).
Node/Group is an Absolute position in the diagram, Right?.

My problem is when I set the position of child Group, position of the parent is no more correct here an example:
Only parent
image
With a child:
image

JJ

Does your Group template have a GroupPanel? If so and if there is no layout positioning the group, the group will get its location from where its members are. But if there is a layout positioning the group, it will move that node (which happens to be a group) to where it thinks that node should be. That would include moving that group’s members.

In your case, are “Node1” and “Node2” top-level nodes? If so, is there a Diagram.Layout, and how is it declared?

Yes Group template have a GroupPanel (see below template implementation)

Diagram have a self implemented layout.
For the moment I simply put all root (top-level) group side by side.
Layout inside the group panel do the same.

Here my Group template implementation (same for all Group):

<DataTemplate x:Key="GraphGroupTemplate">
    <Border CornerRadius="0" 
            BorderThickness="{Binding Data.ViewModel.IsSelected, Converter={StaticResource trueTo2}}" 
            BorderBrush="{Binding Data.ViewModel.IsSelected, Converter={StaticResource trueToRed}}"
            gowpf:Group.SelectionAdorned="False"
            gowpf:Group.LocationElementName="myNetworkPanel"
            gowpf:Group.IsSubGraphExpanded="{Binding Data.ViewModel.IsTreeExpanded, Mode=TwoWay}"
            gowpf:Group.LayoutId="{Binding Data.MyLayoutId}"
            gowpf:Group.Location="{Binding Data.MyPosition, Mode=TwoWay}"
            Margin="0" Padding="0"
            Background="{Binding Data.ViewModel.ProtocolDefinitionVM, Converter={StaticResource protocolToBrush}}">
      <StackPanel>
        <DockPanel HorizontalAlignment="Center" MinHeight="25" Margin="5 2">
          <Image>
            <Image.Source>
              <MultiBinding Converter="{StaticResource mOsiToImage}">
                <Binding Path="Data.ViewModel.ProtocolDefinitionVM.Layer"/>
                <Binding Path="Data.ViewModel.NodeType"/>
                <Binding Path="Data.ViewModel.Type"/>
              </MultiBinding>
            </Image.Source>
          </Image>
          <TextBlock Text="{Binding Data.ViewModel.Name}" Margin="5,5,5,5" FontWeight="Bold" />
          <Button x:Name="myCollapseExpandButton" Command="{Binding Data.ViewModel.ExpandCollapseCommand}" Background="Transparent" Margin="0"                  BorderThickness="0" GotFocus="myCollapseExpandButton_GotFocus" Visibility="{Binding Data.ViewModel.HasVisibleChildren, Converter={StaticResource trueToVisible}}">
            <Button.Content>
              <Image x:Name="b1" Source="{Binding Data.ViewModel.IsTreeExpanded , Converter={StaticResource expandOrCollapseIcon}}" Height="16"/>
            </Button.Content>
          </Button>
        </DockPanel>
        <StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
          <TextBlock Text="Pos:"/>
          <TextBlock Text="{Binding Data.MyPosition, StringFormat=#.00}" Margin="2" Visibility="{Binding Data, Converter={StaticResource visibleIfDebug}}" FontWeight="Medium" />
        </StackPanel>
        <StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
          <TextBlock Text="SubGraphKey:"/>
          <TextBlock Text="{Binding Data.SubGraphKey.Name}" Margin="2" Visibility="{Binding Data, Converter={StaticResource visibleIfDebug}}" FontWeight="Medium" />
        </StackPanel>
        <StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
          <TextBlock Text="IsSubGraph:"/>
          <TextBlock Text="{Binding Data.IsSubGraph}" Margin="2" Visibility="{Binding Data, Converter={StaticResource visibleIfDebug}}" FontWeight="Medium" />
        </StackPanel>
        <StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
          <TextBlock Text="Layout:"/>
          <TextBlock Text="{Binding Data.MyLayoutId}" Margin="2" Visibility="{Binding Data, Converter={StaticResource visibleIfDebug}}" FontWeight="Medium" />
        </StackPanel>
        <StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
          <TextBlock Text="Data.Key:"/>
          <TextBlock Text="{Binding Data.Key}" Margin="2" Visibility="{Binding Data, Converter={StaticResource visibleIfDebug}}" FontWeight="Medium" />
        </StackPanel>
        <StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
          <TextBlock Text="IsTreeExpanded:"/>
          <TextBlock Text="{Binding Data.ViewModel.IsTreeExpanded}" Margin="2" Visibility="{Binding Data, Converter={StaticResource visibleIfDebug}}" FontWeight="Medium" />
        </StackPanel>
        <StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
          <TextBlock Text="ArtOrigin:"/>
          <TextBlock Text="{Binding ElementName=Layout, Path=ArrangementOrigin, StringFormat=#.00}" Margin="2" Visibility="{Binding Data, Converter={StaticResource visibleIfDebug}}" FontWeight="Medium" />
        </StackPanel>
        <StackPanel Margin="5 0" HorizontalAlignment="Center">
          <gowpf:GroupPanel x:Name="myNetworkPanel"  Padding="2 0 2 4" />
          <Border Margin="0" HorizontalAlignment="Center" BorderThickness="0" BorderBrush="Black">
            <Border.Visibility>
              <MultiBinding Converter="{StaticResource falseOrFalseToVisible}">
                <Binding Path="Data.ViewModel.HasVisibleChildren"/>                
                <Binding Path="Data.ViewModel.IsTreeExpanded"/>
              </MultiBinding>
            </Border.Visibility>
            <StackPanel RenderTransformOrigin="0.5,0.5" >
              <TextBlock Text="{Binding Data.ViewModel.ProtocolDefinitionVM.DisplayName}" Margin="2" FontWeight="Medium" HorizontalAlignment="Center" />
              <WrapPanel HorizontalAlignment="Center" Visibility="{Binding Data.ViewModel.NodeType, Converter={StaticResource nodeNetworkToCollapsed}}">
                <TextBlock Text="{Binding Data.ViewModel.NetworkVM.Name}" Margin="2"  FontWeight="Medium" />                
                <TextBlock Text=" / " Margin="2" FontWeight="Medium" />                
                <TextBlock Text="{Binding Data.ViewModel.NodeVM.Name}" Margin="2" FontWeight="Medium" />
              </WrapPanel>              
            </StackPanel>
          </Border>
        </StackPanel>
      </StackPanel>
      <gowpf:Group.Layout>
        <tools:NodeKeyLayout x:Name="Layout" Id="{Binding Data.Key.Name}" DataContext="{Binding Group}"/>
      </gowpf:Group.Layout>
    </Border>
  </DataTemplate>

As you can see GroupPanel is defined. LocationElementName is set to this group panel.

So you have defined your own DiagramLayout class and assigned Diagram.Layout an instance of your class. What does its DoLayout do?

Simply set node Location like this

foreach (var item in nodes)
{
        item.Location = p;
        p.X += item.ActualWidth + 0;
}

You should call Node.Move, because that will also move the members of groups.

thx, it solve my problem

A Remark, when I used CircularLayout with only 1 node there’s no refresh when I add a new node to le collection of the nodes. It works fine when there is at least 2 Nodes (is this a Bug? I’m using GoWPF v2.2.4.45)

I find that CircularLayout works correctly when there is just one node or when there are just two nodes. (In the latter case it just positions the nodes next to each other.)

What behavior are you seeing?

Here an example with 2 nodes added to node source before first DoLayout call

image
With 2 mores nodes
image

and 2 nodes added to node source with DoLayout call after each add
image
With 2 mores nodes
image

As you can see all nodes are all placed at the same position.

Circular Layout is used with default parameters.

Why would you be calling DoLayout on the value of Diagram.Layout? Are you executing a transaction for each time that you add (or remove) a collection of nodes? A transaction will automatically make sure that if the layout has been invalidated that it is performed again at the end of the transaction.