TransformToAncestor给了我错误的变换

时间:2015-02-11 07:28:37

标签: c# .net wpf layout

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

但这是我得到的结果:

enter image description here

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

1 个答案:

答案 0 :(得分:0)

好的,我明白了。由于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);
}