TransformToAncestor 给我错误的转换

TransformToAncestor giving me the wrong transform

我是 WPF 的新手,所以这可能是一个新手问题。我正在开发某种图表编辑器,想用线条连接一些元素。其中一些元素将嵌套在其他元素中,并且单行可能会传递不同级别的元素。所以我想做的是在顶部父元素的 OnRender 事件中绘制这些线。这是初步尝试,我在按钮周围使用方块而不是线条,只是为了确保我能够正确定位子元素:

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;
    }
}

但这是我得到的结果:

如果我在 GetRect 方法中将 element.TransformToAncestor(parent).TransformBounds(LayoutInformation.GetLayoutSlot(element)) 替换为 LayoutInformation.GetLayoutSlot(element),它看起来应该是这样,但这只是因为绘图恰好发生在直接父级中的按钮。在我的实际应用程序中,直接父级不会进行绘图,因此我需要能够获得相对于任意父级的插槽。

好的,我明白了。由于 GetLayoutSlot 获取相对于父元素的插槽,并且 TransformToAncestor 包含从子元素到父元素的关系,因此子元素到父元素的距离加倍。因此,更改 GetRect 以从元素的父元素获取祖先修复了问题:

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);
}