Use this custom **Route** class:

[code] public class CustomRoute : Route {

protected override bool ComputePoints() {

bool result = base.ComputePoints();

if (result && this.PointsCount == 3) {

Point s = GetPoint(0);

Point m = GetPoint(1);

Point e = GetPoint(2);

double dx = e.X-s.X;

double dy = e.Y-s.Y;

double dist = Math.Sqrt(dx*dx + dy*dy);

double space = dist/2-Math.Min(15, dist/3);

double angle = GetAngle(dx, dy);

double offX = Math.Cos(angle)*space;

double offY = Math.Sin(angle)*space;

SetPoint(1, new Point(m.X - offX, m.Y - offY));

InsertPoint(2, new Point(m.X + offX, m.Y + offY));

}

return result;

}

```
public static double GetAngle(double x, double y) {
double A;
if (x == 0) {
if (y > 0)
A = Math.PI/2;
else
A = 3*Math.PI/2;
} else if (y == 0) {
if (x > 0)
A = 0;
else
A = Math.PI;
} else {
if (Double.IsNaN(x) || Double.IsNaN(y)) return 0;
A = Math.Atan(Math.Abs(y/x));
if (x < 0 && y < 0) A -= Math.PI;
else if (x < 0) A = Math.PI-A;
else if (y < 0) A = -A;
}
return A;
}
```

}[/code]

Your **Link** **DataTemplate**(s) should be like:

```
<go:LinkPanel go:Part.SelectionAdorned="True" go:Part.SelectionElementName="Path">
<go:Link.Route>
<local:CustomRoute />
</go:Link.Route>
<go:LinkShape Name="Path" Stroke="Black" StrokeThickness="2" />
<Path go:LinkPanel.ToArrow="OpenTriangle" Stroke="Black" go:LinkPanel.Index="-2" />
<Path go:LinkPanel.FromArrow="BackwardOpenTriangle" Stroke="Black" go:LinkPanel.Index="1" />
</go:LinkPanel>
```

Here’s what results:

If the user drags one of the nodes:

Hi,thank you! I implement it!

The Image Can’t Show?

I’m sorry, but I can’t recover any image from your posts.

Well, if there was something wrong with what I coded, perhaps you can fix it.

Another solution is to change the Link DataTemplate depending on the number of duplicate links.

Perhaps the “normal” case, when there are no duplicate links, is to use a simple link shape with two arrowheads at the ends (i.e. go:LinkPanel.Index=“0” and ="-1", but those get set automatically if you set go:FromArrow and go:ToArrow instead.)

Then when there are duplicate links you can change the link data Category to refer to the LinkTemplateDictionary entry that is defined with the DataTemplate defined above that uses the CustomRoute.

It's the image!

The code I wrote above didn’t account for just a single link, which would cause there to be just two points in the route.

```
protected override bool ComputePoints() {
bool result = base.ComputePoints();
var toarrowhead = this.Link.FindNamedDescendant("To");
var fromarrowhead = this.Link.FindNamedDescendant("From");
if (result && this.PointsCount == 3) {
Point s = GetPoint(0);
Point m = GetPoint(1);
Point e = GetPoint(2);
double dx = e.X-s.X;
double dy = e.Y-s.Y;
double dist = Math.Sqrt(dx*dx + dy*dy);
double space = dist/2-Math.Min(15, dist/3);
double angle = GetAngle(dx, dy);
double offX = Math.Cos(angle)*space;
double offY = Math.Sin(angle)*space;
SetPoint(1, new Point(m.X - offX, m.Y - offY));
InsertPoint(2, new Point(m.X + offX, m.Y + offY));
LinkPanel.SetIndex(toarrowhead, -2);
LinkPanel.SetIndex(fromarrowhead, 1);
} else {
LinkPanel.SetIndex(toarrowhead, -1);
LinkPanel.SetIndex(fromarrowhead, 0);
}
return result;
}
```

And change the LinkTemplate not to assign the LinkPanel.Index statically, but in the code above:

```
<go:LinkPanel go:Part.SelectionAdorned="True" go:Part.SelectionElementName="Path">
<go:Link.Route>
<local:CustomRoute />
</go:Link.Route>
<go:LinkShape Name="Path" Stroke="Black" StrokeThickness="2" />
<Path x:Name="To" go:LinkPanel.ToArrow="OpenTriangle" Stroke="Black" />
<Path x:Name="From" go:LinkPanel.FromArrow="BackwardOpenTriangle" Stroke="Black" />
</go:LinkPanel>
```

oh,thank you walter!

hi,walter!

I don’t know – did you specify values for the **Route.Curviness** property rather than letting them be defaulted?

You’ll need to debug your code to figure out what’s going on. Obviously you have the source code, above, plus the link template(s) and whatever you are doing to create links.