Creating Groups

If the NodesSource property value implements INotifyCollectionChanged, the model adds an CollectionChanged listener which calls GraphLinksModel.DoNodeAdded. So when you add data to the collection, the model is notified.

If the NodesSource property value does not implement INotifyCollectionChanged, then when you call AddNode, which calls InsertNode, which actually adds the data to the collection, and (because the collection does not implement INotifyCollectionChanged) it explicitly calls DoNodeAdded.

So either way DoNodeAdded is called, and that common code is what actually calls PartManager.AddNodeForData for each Diagram. That method finds the data object’s Category and whether it IsGroup. It then calls PartManager.FindTemplateForNode, which finds the appropriate template.

I suppose you could break at FindTemplateForNode to see what it returns.

OK, I’ve never used GroupTemplateDictionary as I’ve only have 1 Group template.
For testing, I’ve added a value String MyCategory in GraphLinksModelNodeData object.

MyCategory = "GraphGroupTemplate";

I’ve added groupTemplate inside a DataTemplateDictionary:

<gowpf:DataTemplateDictionary x:Key="Group">
    <DataTemplate x:Key="GraphGroupTemplate" DataType="{x:Type viewModel:GraphNodeViewModel}">
. . .

Set Category path

model.NodeCategoryPath = "MyCategory";

And finally I’ve set the Group Template to the diagram

GroupTemplateDictionary="{StaticResource Group}"

Then to verify values from part manager Ive made following test:

public void Test(object data)
{
   var cat = FindCategoryForNode(data, Diagram.Model, true, true);
   var c = FindTemplateForNode(data, Diagram.Model, true, true, "GraphGroupTemplate");
}


Category is still not recognized.
FindTemplateForNode(data, Diagram.Model, true, true, “GraphGroupTemplate”) return an DataTemplate object

Do I really have to use a dictionary if I only have one template for group.?

AddNodeForData still return a Node.

No, if there is only one template for Groups, you can just set Diagram.GroupTemplate and you won’t care about category.

How does that data object declare itself to be a Group rather than a regular Node?

In Construtor property IsSubGraph is set to true.

So if you call GraphLinksModel.GetIsGroupForNode on that data object, it returns true, yet the Node that is created isn’t an instance of Group? If so, I cannot explain that.

GraphLinksModel.GetIsGroupForNode return false

with data object:
public class GraphNodeViewModel : GraphLinksModelNodeData
and model
new GraphLinksModel<GraphNodeViewModel, string, string, GraphConnectionViewModel>();

OK, well, that method returning false explains why the Node isn’t also a Group.

But why GetIsGroupForNode is returning false for that object when its IsSubGraph property is true, is very odd to me. You already said that GraphLinksModel.NodeIsGroupPath is “IsSubGraph”, so it isn’t that the model is checking the wrong property to decide whether the data is supposed to be represented by a Group instead of a Node. So I cannot explain that behavior with the information I have. I suppose I would check the value of GraphLinksModel.NodeIsGroupPath again.

It is the case that one cannot change some data to be represented by a Group instead of a Node after the data has been added to the model, nor the other direction, changing a Group back into a Node. That limitation is probably not applicable here, but I thought I should mention it just in case.

GraphLinksModel.NodeIsGroupPath = “IsSubGraph”

Are you still calling PartManager.MakeNodeForData, even though you probably shouldn’t be?

That is the method that actually constructs either a new Node or a new Group, depending on the isgroup argument. It is only called by PartManager.AddNodeForData, as I explained above.

Nope, I do not call MakeNodeForData anymore. I only call AddNodeForData (As it is in Virtualization example), as you told me.

The only difference between working and not working code is the collection declaration.

So what do you use for the source collection? Does it implement INotifyCollectionChanged?

Once it an ObservableCollection and the other it’s a normal Collection.
As I initiate the node creation with PartManager.AddNodeForData I do not see any reason to manage a collection notification.

I just tried a random sample involving groups. I changed the two sources from ObservableCollection to Collection. Everything seems to work well, even after copying a group. The Collection has been modified correctly, as far as I can tell.

Hi Walter,

I’m come back to this purpose. Reading again your comments show me that I’ve never called DoNodeAdded method in the case of a standard list of Node. this may explain why I’ve always had a Node part and not a Group Part in my previously tests.

Here is the process I use to manage groups without observable collection.

1/ When a group is new, I call DoNodeAdded to add it to my Model. Regarding to Virtualization it will or not create a Part in the ViewPort.

2/ When a Group is already in added to my Model, I call Method AddNodeForData to add visible groups in the ViewPort.

Do you agree with this process? At least it works as I expected it.

In my environment it’s possible to insert a group between 2 groups. With an observable collection it wasn’t a problem subgraph was set in group and part was properly linked to it’s parent. But now when I’m inserting a group between 2 other group, the deeper group is not linked to it’s new subgraph, it’s linked to nothing?

Here a comparison between same Part inserted (left) and when part is added (right)

As ContainingSubGraph is only a get property, I can imagine that I miss a call notification to be able to actualized/synchronized the part value when SubgraphKey has been changed.

Could you help me please.

Hi Walter,

I think I’ve got it.

A change in my node (for ex. SubgraphKey) has to be synchronized with Model Node Source via DoGroupNodeCHanged.
Then if I process my list in the right order (from higher group to deeper group) everything look fine.
Do you agree, the sorting process. If so can you tell me/confirm that you use an intern sorting algorithm to process internally your Node list?

For the moment I’ve done it only for Node, but I think that I’ve to apply same process for Links, when for example from or to are modified.

Yes, GraphLinksModel was implemented so that the order in which the data is provided does not matter. (Same goes for the other model classes.)
Or are you asking a different question?

Hi Walter,

Is there a way to (re)calculate a link route when “from” or “to” node is outside the view port.
Position of the missing node is known.
I would like to avoid adding each missing nodes to the diagram.
Reason is that it’s possible to have a node connected to 1000+ other nodes.
Adding all missing nodes takes time and resources, and affect performances.

Thanks a lot, and enjoy your week-end.

So you are implementing virtualization. OK, I suppose you could:

  • just set the Link.Route’s Route.Points
  • override Route.ComputePoints to handle routing to a missing Node the way that you want
  • maybe some other choices, depending on the requirements

Problem solved

A post was split to a new topic: Overview initialization