GoWPF 3.0.3 - Copied Links Curve is not Bezier

Hi, i have a problem, that when i copy some parts, in my sample 2 nodes and 1 link, then the link does not have the same curve as the original one.

In the following image, you can see, the original top link is a bezier curve, and the copied bottom link suddenly ain’t a bezier curve.

image

My link template is pretty straight forward:

        <DataTemplate x:Key="LinkTemplate">
            <go:LinkPanel go:Part.SelectionElementName="Path" go:Part.SelectionAdorned="True"
                          go:Part.SelectionAdornmentTemplate="{StaticResource LinkSelectionAdornmentTemplate}"
                          go:Part.Reshapable="True">
                <go:Link.Route>
                    <go:Route Routing="Normal" Curve="Bezier"
                              FromEndSegmentDirection="RotatedNodeOrthogonal"
                              ToEndSegmentDirection="RotatedNodeOrthogonal"
                              RelinkableFrom="True" RelinkableTo="True"
                              LinkReshapeHandleTemplate="{StaticResource LinkReshapeHandleTemplate}" />
                </go:Link.Route>

                <!--This is the from-arrow-->
                <Path Fill="{Binding Path=Data.BackColor}"
                      go:LinkPanel.FromArrow="{Binding Path=Data.FromArrow}" 
                      go:LinkPanel.FromArrowScale="{Binding Path=Data.FromArrowScale}" />

                <!--This is transparent thicker shape for easier selection-->
                <go:LinkShape Stroke="Transparent" StrokeThickness="5" />
                
                <!--This is the actual from-to path-->
                <go:LinkShape x:Name="Path" 
                              Stroke="{Binding Path=Data.BackColor}"       
                              StrokeDashArray="{Binding Path=Data.DashArray}"
                              StrokeThickness="{Binding Path=Data.Thickness}" />

                <!--This is the to-arrow-->
                <Path Fill="{Binding Path=Data.BackColor}"
                      go:LinkPanel.ToArrow="{Binding Path=Data.ToArrow}" 
                      go:LinkPanel.ToArrowScale="{Binding Path=Data.ToArrowScale}" />

                <!--This is the from-text-->
                <TextBlock Text="From" go:LinkPanel.Index="0"
                   go:LinkPanel.Offset="NaN NaN"
                   go:LinkPanel.Orientation="Upright" />
                
                <!--This is the mid-text-->
                <TextBlock Text="Mid"
                   go:LinkPanel.Offset="0 NaN"
                   go:LinkPanel.Orientation="Upright" />

                <!--This is the to-text-->
                <TextBlock Text="To" go:LinkPanel.Index="-1"
                   go:LinkPanel.Offset="NaN NaN"
                   go:LinkPanel.Orientation="Upright" />
            </go:LinkPanel>
        </DataTemplate>

If i drag and drop a new link, then the curve is good, just when i copy a link, i ran into this behavior?
Any idea why this is happening? - Or solution of how i could solve this?

I also tried, to add a “Curve” property to my link data. and bind it within the template, same result. - Copied link curves are never Bezier.

Well, the copy might still be a Bezier curve, with the control points on the straight line. Look at it in the debugger.

You only have one link template, yes?

Yes, only one link template.
If i then manually add another link i got this result:
image

That’s normal.

What’s the value of Curviness for the Link.Route in the single copied Link?
Hmmm, it probably isn’t zero, or else adding a link wouldn’t have caused it to be curved automatically.

I bind the curviness like this:

To the following properties:

No matter if i created a new link or it is a copied one the “Curviness” is always double.NaN.
It seems like, the Curviness gets calculated when i add a new link manually, but not, when the link is copied.

Hmm, is the only way to achieve non overlapping links, to calculate the curviness manually depending on how many link the source and target node share? - Or is there something, what i can call to update this curviness calculation?

Many thanks in advance, Hannes

Bottom is a copy of the top:
image

My problem is still, that copied links are overlapping. - No matter what LinkCurve i use. (Tried Bezier and None)

If you remove the settings and bindings of the Route.Curviness property, does that help?

Before:

Now i tried to changed to:

Result is the same:
image

Actually, it isn’t clear to me whether your links are Bezier curves or just straight segments. They appear to be the latter, but your Binding might be setting them otherwise.

In either case, the curviness, when it is NaN, is automatically calculated for each link route by the Route.ComputeCurviness method.

Are you sure that the copied nodes and links actually have two links going between the two copied nodes?

I tried this in a sample and the copied links correctly curved away from each other.

Maybe you can tell me what i am doing wrong by having a look at my educational solution where this happens too.

HannesHold/GoWPF: Some educational project to explore the GoWPF application (github.com)

image

Many thanks in advance, Hannes

What i see in the output is the following:
System.Runtime.InteropServices.COMException (0x800401D3): Daten in Zwischenablage sind ungültig. (0x800401D3 (CLIPBRD_E_BAD_DATA))
at System.Runtime.InteropServices.ComTypes.IDataObject.GetData(FORMATETC& format, STGMEDIUM& medium)
at System.Windows.DataObject.OleConverter.GetDataFromOleHGLOBAL(String format, DVASPECT aspect, Int32 index)
at System.Windows.DataObject.OleConverter.GetDataFromBoundOleDataObject(String format, DVASPECT aspect, Int32 index)
at System.Windows.DataObject.OleConverter.GetData(String format, Boolean autoConvert, DVASPECT aspect, Int32 index)
at System.Windows.DataObject.OleConverter.GetData(String format, Boolean autoConvert)
at System.Windows.DataObject.GetData(String format, Boolean autoConvert)
at System.Windows.Clipboard.GetDataInternal(String format)
at System.Windows.Clipboard.GetData(String format)
at Northwoods.GoXam.CommandHandler.PasteFromClipboard()
at Northwoods.GoXam.CommandHandler.Paste()

Maybe this causes the problem somehow.

Make sure all of your data is serializable.

Ok, i made LinkData and NodeData serializable. - This error is gone. - But still facing the issue that a copied link is straight.

What is the value of the copied Link’s Route.Curviness? NaN?
Are there any other values of the copied Route compared with the original Route that are different, besides the Points?

Good morning Walter.

Since i am not using any binding on Curve or Curviness anymore, i did the following.
I use a custom PartManager and override void OnLinkAdded(Link link) and filled it with logs concerning those values.

User actions:

  1. Drag and drop a node to the diagram
  2. Drag and drop a second node to the diagram
  3. Add a link via drag and drop between those nodes

Result looks like this:
image

Logs:
Entering OnLinkAdded(Link link)
Link.Route.Curve=‘None’, Link.Route.Curviness=‘NaN’
Calling base.OnLinkAdded(link)
Link.Route.Curve=‘None’, Link.Route.Curviness=‘NaN’
Exiting OnLinkAdded(Link link)
Entering OnLinkAdded(Link link)
Link.Route.Curve=‘Bezier’, Link.Route.Curviness=‘NaN’
Calling base.OnLinkAdded(link)
Link.Route.Curve=‘Bezier’, Link.Route.Curviness=‘NaN’
Exiting OnLinkAdded(Link link)
Entering OnLinkAdded(Link link)
Link.Route.Curve=‘Bezier’, Link.Route.Curviness=‘NaN’
Calling base.OnLinkAdded(link)
Link.Route.Curve=‘Bezier’, Link.Route.Curviness=‘NaN’
Exiting OnLinkAdded(Link link)

User actions:
4) Then i select the both nodes including the link by pressing CTRL + A
5) Copiing them by pressing CTRL + C
6) And paste them by pressing CTRL +V

Result looks like this: (Straight link, but here i expect a “Curved one”)
image

Logs:
Entering OnLinkAdded(Link link)
Link.Route.Curve=‘None’, Link.Route.Curviness=‘NaN’
Calling base.OnLinkAdded(link)
Link.Route.Curve=‘None’, Link.Route.Curviness=‘NaN’
Exiting OnLinkAdded(Link link)
Entering OnLinkAdded(Link link)
Link.Route.Curve=‘Bezier’, Link.Route.Curviness=‘NaN’
Calling base.OnLinkAdded(link)
Link.Route.Curve=‘Bezier’, Link.Route.Curviness=‘NaN’
Exiting OnLinkAdded(Link link)

The problem is kind of reproducable with having just a single link. - On the single link i also would also consider this as wanted behavior concerning the curviness being 0 or NaN.

But having multiple links, all having the same curviness result in overlapping links which is a suboptimal situation.

When i try to bind the Curviness and calculate it on my own then it works as well. I would rather like to use the build-in functionality where the curviness is calculated.

I also had a look using ILDASM, and i can see that for calulcation a BundleIndex is used. Since this is internal i am not able to use it and fear that other my calculation way would not deliver same performance.

I think i might come closer to the reason. - Copied link has 4 points, and the pasted link only 2, seems like if we just have a start and end point, than a curviness calculation wont make sense.

Error somehow is within:

When i debug the sample DraggableLink, it is also the case that “copiedLink” is always null.

So a transfer of route points might anyway be wrong.
However, in the sample, the link wich is passed in OnLinkAdded(Link link) always contains all points.

In my situation, it always contains just two points within OnLinkAdded(Link link).
Within CopyParts, it contains 4 points (origLink), so i assume, those are start and endpoints and the two middle adjustment points.

Thanks for doing that investigation. We’ll look into it soon.

By digging into the API docs, I found out that i have to override Clone() on my link data.
I tried arround a a bit.

    public override bool Equals(object? obj)
    {
        if (obj is not null && obj.GetType() == this.GetType())
        {
            var data = obj as MoLinkData;
            if (data is not null)
            {
                if (data.Id == this.Id)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return base.Equals(obj);
            }
        }
        else
        {
            return base.Equals(obj);
        }
    }

    public override object Clone()
    {
        var clone = base.Clone() as MoLinkData;
        if (clone is not null)
        {
            clone.Id = Guid.NewGuid();
        }

        return clone is null ? base.Clone() : clone;
    }

No i can also see having four points within on LinkAdded(Link link)
Also on UpdateRouteDataPoints i have four points:

I thing this helped a bit, but still does not deliver expected result.
image

It is a straight line, without “Reshapeable points”.

Manually drawn links, all have this “Reshapeable points”.