WPF: Get position of child UIElement within its pa

2020-06-23 08:38发布

问题:

Lets say I have this XAML code:

<DockPanel Name="pan">
    <Label Content="AAA" Name="lab1" />
    <Label Content="BBB" Name="lab2" />
    <Label Content="CCC" Name="lab3" />
</DockPanel>

I my code behind I want to find out what are the coordinates of lab2 within pan. Hovewer I want to ignore any present RenderTransform of lab2. So the solution must return same coordinates for above code and following:

<DockPanel>
    <Label Content="AAA" />
    <Label Content="BBB" >
        <Label.RenderTransform>
            <TranslateTransform Y="20"/>
        </Label.RenderTransform>
    </Label>
    <Label Content="CCC" />
</DockPanel>

In another words I want the position that was set by the ArrangeOverride method of pan when calling Arrange on but2. I would call it 'logical position'. The 'visual position' can be obtained by calling following method:

private Point visualPoss() {
    Point lab2Vis = lab2.PointToScreen(new Point(0, 0));
    Point panVis = pan.PointToScreen(new Point(0, 0));
    return new Point(lab2Vis.X - panVis.X, lab2Vis.Y - panVis.Y);
} 

But this is not a solution of my problem as the return value of this visualPoss() is not equal for both XAML code examples above.

Please leave comment if somehing is unclear.

Thank you

回答1:

It looks like there is very simple and clear solution:

private Point logicalPoss() {
    Vector vec = VisualTreeHelper.GetOffset(lab2);
    return new Point(vec.X, vec.Y);
}

It looks like it is working well. If you know abou the scenerio when it will not work please leave a comment.



回答2:

I would get the transform, and convert it to a MatrixTransform. You can then use the Inverse property to reverse the render transform. It would look something like so:

private Point visualPoss() 
{
    Point lab2Vis = lab2.PointToScreen(new Point(0, 0));
    Point panVis = pan.PointToScreen(new Point(0, 0));

    if (lab2.RenderTransform != null)
    {
        var matrix = new MatrixTransform(lab2.RenderTransform.Value);
        lab2Vis = matrix.Inverse.Transform(lab2Vis);
    }

    return new Point(lab2Vis.X - panVis.X, lab2Vis.Y - panVis.Y);
}