English 中文(简体)
Connecting two WPF canvas elements by a line, without using anchors?
原标题:

I have a canvas for diagramming, and want to join nodes in the diagram by directed lines (arrow ends). I tried the anchor approach, where lines only attach at specific points on the nodes but that did not work for me, it looked like crap.

I simply want a line from the centre of each object to the other, and stop the line at the nodes edge in order for the arrow end to show properly. But finding the edge of a canvas element to test intersections against has proven difficult.

Any ideas?

最佳回答

I got a method working using the bounding box of the element. It is not perfect, since my elements are not perfectly rectangular, but it looks OK.

Basically I find the bounding box of the element in Canvas coordinates by:

    private static Rect GetBounds(FrameworkElement element, UIElement visual)
    {
        return new Rect(
            element.TranslatePoint(new Point(0, 0), visual),
            element.TranslatePoint(new Point(element.ActualWidth, element.ActualHeight), visual));
    }

Then I find the intersection of the centre-to-centre line against each of the four sides of the bounding box, and use that intersection point to connect the two elements by a Line shape.

I found the intersection code at Third Party Ninjas: http://thirdpartyninjas.com/blog/2008/10/07/line-segment-intersection/

private void ProcessIntersection()
    {
        float ua = (point4.X - point3.X) * (point1.Y - point3.Y) - (point4.Y - point3.Y) * (point1.X - point3.X);
        float ub = (point2.X - point1.X) * (point1.Y - point3.Y) - (point2.Y - point1.Y) * (point1.X - point3.X);
        float denominator = (point4.Y - point3.Y) * (point2.X - point1.X) - (point4.X - point3.X) * (point2.Y - point1.Y);

        intersection = coincident = false;

        if (Math.Abs(denominator) <= 0.00001f)
        {
            if (Math.Abs(ua) <= 0.00001f && Math.Abs(ub) <= 0.00001f)
            {
                intersection = coincident = true;
                intersectionPoint = (point1 + point2) / 2;
            }
        }
        else
        {
            ua /= denominator;
            ub /= denominator;

            if (ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1)
            {
                intersection = true;
                intersectionPoint.X = point1.X + ua * (point2.X - point1.X);
                intersectionPoint.Y = point1.Y + ua * (point2.Y - point1.Y);
            }
        }
    }

And voilá! The lines are now drawn as if they go from the centre of each node to the other, but stops approximately at the node s edge so the arrow end is visible.

An improvement of this method would be to test against the actual edge of the node itself, such as for elliptical nodes, but I have yet to find a WPF method that provides me with a Geometry or Path that I can test against.

问题回答

暂无回答




相关问题
WPF convert 2d mouse click into 3d space

I have several geometry meshes in my Viewport3D, these have bounds of (w:1800, h:500, d:25). When a user clicks in the middle of the mesh, I want the Point3D of (900, 500, 25)... How can I achieve ...

Editing a xaml icons or images

Is it possible to edit a xaml icons or images in the expression design or using other tools? Is it possible to import a xaml images (that e.g you have exported) in the expression designer for editing?...

WPF: writing smoke tests using ViewModels

I am considering to write smoke tests for our WPF application. The question that I am faced is: should we use UI automation( or some other technology that creates a UI script), or is it good enough to ...

WPF - MVVM - NHibernate Validation

Im facing a bit of an issue when trying to validate a decimal property on domain object which is bound to a textbox on the view through the viewmodel. I am using NHibernate to decorate my property on ...

How do WPF Markup Extensions raise compile errors?

Certain markup extensions raise compile errors. For example StaticExtension (x:Static) raises a compile error if the referenced class cannot be found. Anyone know the mechanism for this? Is it baked ...

WPF design-time context menu

I am trying to create a custom wpf control, I m wondering how I can add some design-time features. I ve googled and can t seem to get to my goal. So here s my simple question, how can I add an entry ...

How to combine DataTrigger and EventTrigger?

NOTE I have asked the related question (with an accepted answer): How to combine DataTrigger and Trigger? I think I need to combine an EventTrigger and a DataTrigger to achieve what I m after: when ...

热门标签