Programmatic way to re-route links?

I have the following diagram: A->C, B->C. I’m merging nodes A and B together into a single node. (More precisely: I’m merging the business objects behind those nodes and then updating my diagram to reflect the new state.) The resulting diagram is A=>C (two links from A to C). I’m modifying the GraphLinksModelLinkData for the B->C link such that the From property is the A.Key value. The only problem I’m running into is that the modified link is visually on top of the other link. Is there a way to force one or both links to be rerouted so they are not on top of each other? I tried calling Link.Remeasure() on the modified link, but that didn’t have any impact.

Some more details: I am modifying the model inside of a transaction. I have an undo manager, but I need to prevent the user from undoing the modification to the link model’s From value thus I’m setting SkipsUndoManager = true for my transaction. My Link.Route is not data bound; I’m using Bezier curves at the moment, but also need to support straight lines eventually.

If you move the “C” node manually, do the links become distinct?
Using a debugger, what are the FromSpot values for the Link.Routes and for the ports/nodes? Are they Spot.None? If you want the link routing that you can see in the State Chart sample (for example), you need to make sure the spots are “None”. Note also that some layouts will by default set the FromSpot and ToSpot – you’ll need to turn that off.

Manually dragging C does not make the links become distinct.

The FromSpot values for Link.Route and nodes A and B are all Spot.Default. I tried setting the FromSpot and ToSpot on the route to Spot.None with the following code:


<go:Link.Route>
  <go:Route Curve="Bezier" FromSpot="None" ToSpot="None" />
</go:Link.Route>

but that had no effect. I verified in the debugger that the FromSpot values were indeed Spot.None. I’m using just the default DiagramLayout.

I guess something else I’m wondering is this: what’s the proper way to perform a relinking operation? Can I initiate it from the model? And is it acceptable to simply set GraphLinksModelLinkData.From to a new value or do I need to about my change in some other way?

All relationships are completely defined by the model and nothing else.
Every time any code asks about any relationship, it actually goes through the model.
For example, Link.FromNode and Node.ContainingSubGraph all ask the model.

So it should be OK to just set the link data “from” property to reconnect the link. However this does assume that the link data implements INotifyPropertyChanged, and that that property is known by the model to have special meaning regarding link relationships.

Did you want the link routing behavior you see in the State Chart sample?

Thanks for clearing up my model questions. I’ve looked at the State Chart sample and I’m not sure what exactly you mean by the routing behavior in that example. I don’t want users to be able to relink a link from one node to another explicitly through the UI; I do want my model to respond to changes in the rest of my system to programmatically change the end point of a given GraphLinksModelLinkData instance and then have the modified Link object use a Route that doesn’t lay on top of an existing Link. I’ve looked at the State Chart sample and the only thing that sticks out to me are the Route.RelinkableFrom and Route.RelinkableTo properties, but I don’t think that’s what I’m after.

I was referring to the routing of multiple links between the same pair of nodes, not the ability to relink.

Yes, that’s part of what I’m trying to achieve. I’ve already set the Node.LinkableDuplicates attached property to True. Is there something else I need to do?

Is it performing any kind of automatic layout?
TreeLayout and LayeredDigraphLayout normally set the Link.Route.FromSpot and ToSpot according to the general direction of the layout. But you can disable that behavior by setting one or more properties that start with “Sets”.

No, it is not performing any automatic layout. I’m using just the default DiagramLayout that is wired into the Diagram.

Do your nodes have multiple ports?
Do you have any code or binding that is setting the Route.Curviness?