GroupTemplate are not apply

I have a NodeTemplateDictionary and a GroupTemplate but even if the property of my node IsSubGraph is set to true, my group takes the default NodeTemplate instead of the GroupTemplate. I set the paths in my model like this:

MyBase.NodeKeyPath = “Key”
MyBase.NodeIsGroupPath = “IsSubGraph”
MyBase.GroupNodePath = “SubGraphKey”
MyBase.LinkFromPath = “From”
MyBase.LinkToPath = “To”

And nodes contained in the group have the group.key in their SubGraphKey property.

What am I doing wrong?

If you set Diagram.GroupTemplate correctly, I don’t know how to explain that.

I assume the various samples in the demo that make use of groups compile and run as expected, right?

I did exactly the same as what it says in the Introduction to GoXam and I have no idea what can be wrong. Here is a screenshot where I bind the Key, SubGraphKey and IsSubGraph property to my node. Everything seems ok but my Group still take the NodeTemplate.

And here is how I defined my NodeTemplate and GroupTemplate:

        <DataTemplate x:Key="StreamNodeTemplate">
            <go:SpotPanel go:Node.Location="{Binding Path=Data.Location, Mode=TwoWay}"  
                          Background="Transparent" 
                          go:Part.SelectionAdorned="True" go:Part.SelectionAdornmentTemplate="{StaticResource NodeSelectionAdornmentTemplate}" >

                <go:SpotPanel.ToolTip>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="Key:" />
                        <TextBlock Text="{Binding Path=Data.Data.GUID}" />
                        <TextBlock Text="   SubGraphKey:" />
                        <TextBlock Text="{Binding Path=Data.SubGraphKey}" />
                        <TextBlock Text="   IsSubGraph:" />
                        <TextBlock Text="{Binding Path=Data.IsSubGraph}" />
                    </StackPanel>
                </go:SpotPanel.ToolTip>

                <!--<StackPanel>-->
                <go:NodePanel Sizing="Auto">

                    <go:NodeShape x:Name="Icon"
                              go:NodePanel.Figure="Circle"
                              Stroke="Black" StrokeThickness="1"
                              Fill="LightBlue"
                              Margin="12"
                              Width="8" Height="8"
                              go:NodePanel.Spot1="0 0" go:NodePanel.Spot2="1 1"
                              go:Node.PortId=""
                              go:Node.LinkableFrom="True" go:Node.LinkableTo="True" 
                              go:Node.LinkableSelfNode="True" Cursor="Hand"
                              go:Node.LinkableDuplicates="True"
                              Opacity="{Binding Path=Data.Opacity}"/>

                 </go:NodePanel>


                    <!--<TextBlock Text="{Binding Path=Data.Data.GUID,Mode=TwoWay}" TextWrapping="Wrap" 
                           HorizontalAlignment="Center" VerticalAlignment="Center"
                           go:Part.TextEditable="True"
                           Opacity="{Binding Path=Data.Opacity}"/>-->
                <!--</StackPanel>-->

            </go:SpotPanel>
        </DataTemplate>
        <DataTemplate x:Key="StreamGroupTemplate">
            <StackPanel go:Node.LocationElementName="myGroupPanel">
                <TextBlock x:Name="Label" Text="{Binding Path=Data.Data.GUID}" FontSize="16" FontWeight="Bold" HorizontalAlignment="Center" />
                <Border x:Name="myBorder" CornerRadius="5" BorderBrush="Green" BorderThickness="2" >
                    <go:GroupPanel x:Name="myGroupPanel" Padding="5" />
                </Border>
            </StackPanel>
        </DataTemplate>
    <customGoXam:CustomDiagram x:Name="objDiagram"
                Grid.Column="2"
                AllowDrop="True"
                GridVisible="False" GridSnapEnabled="True" GridSnapCellSize="10 50" 
                Background="{StaticResource DiagramBackgroundBrush}"
                LinkTemplateDictionary="{StaticResource DiagramLinkTemplateDictionary}" 
                NodeTemplateDictionary="{StaticResource DiagramNodeTemplateDictionary}" 
                GroupTemplate="{StaticResource StreamGroupTemplate}"
                HorizontalContentAlignment="Center" VerticalContentAlignment="Center">           

    </customGoXam:CustomDiagram>

Well, that does look correct.

Might you have changed your node data’s IsSubGraph property after the node data had been added to the model? GoXam assumes that that property value never changes. So a regular Node DataTemplate will have been applied before it knows that it’s supposed to be a Group.

No, I set the IsSubGraph property in the constructor of my node and anywhere else…

By the way, thank you for the quick answer!

The only thing I could see is that I modify the SubGraphKey of my Node without using the Start/CommitTransaction. Can it affect the result?

That wouldn’t change how it appeared – it should still be some text above a green-bordered rounded rectangle. If it didn’t have any members, it would still be 10x10 big.

I suppose you could override GraphLinksModel.FindIsGroupForNode to set a breakpoint to see what it returns for each node data.

I overrided FindIsGroupForNode and it returns what I expected… False for the 2 Nodes and True for the Group…

OK. Check that GraphLinksModel.FindCategoryForNode is returning the expected category name.

And then check that PartManager.FindCategoryForNode is returning the expected category too.

And see if PartManager.FindTemplateForNode is getting the expected DataTemplate.

Finally see if PartManager.MakeNodeForData is really returning a Group for node data that you believe represents a group.

Are there any PartManager or GraphLinksModel methods that you have overridden, other than for debugging?

Ok, did what you asked and here is what I found.

PartManager.FindCategoryForNode doesn’t return the right Category. And another thing, the “isGroup” parameter is true then it should be false.

Same in the PartManager.FindTemplateForNode and PartManager.MakeNodeForData, parameter “isGroup” is false.

If I manually return the right Category and set the isGroup parameter to the right value, it works but my nodes are not embedded in my group (see picture below).

And yes, I overrided methods in GraphLinksModel:

  • FindToNodeKeyForLink/FindFromNodeKeyForLink where I manually return the FromKey instead of calling the base class method
  • InsertLink where I manually add the link to the LinksSource instead of calling the base class method
  • MakeNodeKeyUnique Return true all the time except when the nodedata parameter is null
  • ModifyLinkFromPort/ModifyLinkToPort I don't think this method is the cause of my problem

Are you saying that PartManager.FindCategoryForNode is being called on a node data that should be considered to be a group but the “isGroup” argument is false when it should be true? Well, that would explain the behavior. Now we need to figure out why that argument is false.

To review the whole process, including things you can check:

  • GraphLinksModel.FindIsGroupForNode is called once to determine if the node data “is a group”; this value is remembered
  • GraphLinksModel.GetIsGroupForNode is called, possibly many times, to decide if the model thinks the node data “is a group”. This returns the value remembered from the call to FindIsGroupForNode, which is why one cannot change the value dynamically. This is called by…
  • PartManager.AddNodeForData which passes the value from GetIsGroupForNode to the various methods that I mentioned before (FindCategoryForNode, FindTemplateForNode). But in your case it’s too late – the value is wrong. So further investigation of all three of these methods is unnecessary.

My guess is that GraphLinksModel.GetIsGroupForNode is returning the wrong value because it appears to have changed. Might there be a duplicate key? That would really cause confusion.

And you need to check whether the node data have the same key as their “group key”. The methods are GraphLinksModel.GetGroupForNode and FindGroupKeyForNode.

Hi Walter,

Is method FindGroupKeyForNode is called only once? because my nodes are created before my group. In order, that’s what happens:

  1. Create the 2 nodes
  2. FindGroupKeyForNode is called for each nodes and returns the right value(null) because, at this moment, the group is not created yet
  3. Create the group
  4. FindGroupKeyForNode is called for the group but it never called for the nodes again
And indeed, GetIsGroupForNode returns the wrong value when I called it for the group.

And no, there is no duplicate Key. I browse the NodesSource and every node has a different key…

If FindGroupKeyForNode is returning the “wrong” value, null, initially, that implies that you are modifying the node’s state to give it a reference to the group data, via its key. Are you calling SetGroupNodeKey to do that, or does the property setter call RaisePropertyChanged? If neither is true, the model won’t know that the value of FindGroupKeyForNode will have changed.

Maybe you should create all of your node data before you add them to the model by assigning the NodesSource collection.

No, FindGroupKeyForNode returns the right value the first time because the group is not yet created. But when I create the group, FindGroupKeyForNode is not called a second time for the nodes, even if the SubGraphKey property of my nodes have changed. That’s why I asked you if FindGroupKeyForNode is only called once for each node.

And no I didn’t call SetGroupNodeKey to nofity model that the SubGraphKey changed. I tried, and directly after, I called GetIsGroupForNode but this method returns again false.

Does your node data class implement INotifyPropertyChanged and does its SubGraphKey property setter call RaisePropertyChanged (and only if the value has actually changed)?

If the data is part of the model, the model’s PropertyChanged event handler for that data will be called with a property change using the name “SubGraphKey”. If that matches the GraphLinksModel.GroupNodePath, then the model knows that the data is changing its group membership.

If the data is not (yet) part of the model, then nothing happens until the data is added to the model.

In either case GraphLinksModel.FindGroupKeyForNode will be called, so that the model can find and remember any group that it’s supposed to be a member of.

I got it!!! It never too late.

It was because I was overriding the GraphLinksModelNodeData.OnPropertyChanged whitout calling the base class method or without raising the property changed event. I feel so stupid right now :P

Thank for the help Walter!