简体   繁体   中英

TransformToAncestor giving me the wrong transform

I'm new to WPF so this may be a newbie question. I'm working on some kind of diagram editor, and want to connect some elements with lines. Some of these elements will be nested inside other elements, and a single line may pass over elements in different levels. So what I want to do is draw these lines in the OnRender event in the top parent element. Here is a preliminary attempt, where instead of lines I'm using squares around buttons, just to make sure I'm able to properly locate the child elements:

public class Container : Border
{
    public readonly StackPanel Panel = new StackPanel();
    private readonly Pen _Pen = new Pen(Brushes.Red, 2);

    public Container()
    {
        Panel.Orientation = Orientation.Vertical;
        Panel.Children.Add(MakeButton("One"));
        Panel.Children.Add(MakeButton("Two"));
        Panel.Children.Add(MakeButton("Three"));
        Child = Panel;
    }

    private Rect GetRect(Visual parent, FrameworkElement element)
    {
        return element.TransformToAncestor(parent).TransformBounds(LayoutInformation.GetLayoutSlot(element));
    }

    protected override void OnRender(DrawingContext dc)
    {
        base.OnRender(dc);

        foreach (Button item in Panel.Children)
        {
            var box = GetRect(this, item);
            dc.DrawRectangle(Brushes.Transparent, _Pen, box);
        }
    }

    private static Button MakeButton(string text)
    {
        Button button = new Button();
        button.Content = text;
        button.Padding = new Thickness(10);
        button.Margin = new Thickness(5);
        return button;
    }
}

But this the result I get:

在此处输入图片说明

If I replace element.TransformToAncestor(parent).TransformBounds(LayoutInformation.GetLayoutSlot(element)) with LayoutInformation.GetLayoutSlot(element) in the GetRect method, It'll look the way is supposed to, but only because the drawing happens to occur in the direct parent of the buttons. In my actual application the direct parent won't be doing the drawing, so I need to be able to get the slot relative to any arbitrary parent.

OK I figured it out. Since GetLayoutSlot gets the slot relative to the parent, and TransformToAncestor includes the relation from child to parent, it's doubling the distance from the child element to the parent. So changing GetRect to get the ancestor from the element's parent fixes the problem:

private Rect GetRect(Visual ancestor, FrameworkElement element)
{
    Visual parent = element.Parent as Visual;
    var transform = parent.TransformToAncestor(ancestor);
    var slot = LayoutInformation.GetLayoutSlot(element);
    return new Rect(transform.Transform(slot.TopLeft), slot.Size);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM