4

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

Rasto
  • 17,204
  • 47
  • 154
  • 245

2 Answers2

6

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.

Rasto
  • 17,204
  • 47
  • 154
  • 245
3

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);
} 
Abe Heidebrecht
  • 30,090
  • 7
  • 62
  • 66
  • one tweak... you probably want to walk all the way up the visual tree and apply the inverse of each rendertransforms you encounter – Robert Levy Jan 21 '11 at 17:28
  • Good point for a general method. Since the element is a child of the panel that he is concerned about comparing, I didn't think it was necessary in this case. – Abe Heidebrecht Jan 21 '11 at 17:35
  • I'm sorry to dissapoint you but I have tryied something very similar to this and it did not work - the only defference is that I created inverse transformation right from the original like this: `lab2.RenderTransform.Inverse.Transform(lab2Vis)`. I don't know why, but it did not translate the coordinates back to the original location. – Rasto Jan 21 '11 at 18:41