Determine the bounding rect of a WPF element relative to some parent
Asked Answered
O

4

19

I consider this a pretty simple request, but I can't seem to find a conclusive answer in my searches. How can I determine the bounds of a particular visual element in my window, relative to some other parent element?

I've tried using LayoutInformation.GetLayoutSlot but this just seems to return a Rect at 0,0 and doesn't reflect the actual location of the element.

What I'm trying to do is take a "screenshot" of a window using RenderTargetBitmap and then crop it to a particular element, but I can't get the element's bounds to know what to crop the bitmap to!

Overstay answered 12/8, 2010 at 22:2 Comment(0)
C
21

It is quite simple:

public static Rect BoundsRelativeTo(this FrameworkElement element,
                                         Visual relativeTo)
{
  return
    element.TransformToVisual(relativeTo)
           .TransformBounds(LayoutInformation.GetLayoutSlot(element));
}

In fact it may be overkill to put it in a separate method.

Chrisom answered 13/8, 2010 at 5:35 Comment(2)
GetLayoutSlot gets the space that's allocated in the layout for the element, but the actual element size could be different if it has an explicit width/height and/or a transform. To get the "true" size rect, try element.RenderTransform.TransformBounds(new Rect(element.RenderSize)).Dethrone
This didn't work for me, see Mauro Sampletro's or DanW's answer below which does work.Dumdum
M
9

The LayoutSlot option didn't work for me at all. This ended up giving me a child position relative to a specified parent/ancestor control:

    public static Rect BoundsRelativeTo(this FrameworkElement child, Visual parent)
    {
        GeneralTransform gt = child.TransformToAncestor(parent);
        return gt.TransformBounds(new Rect(0, 0, child.ActualWidth, child.ActualHeight));
    }
Minton answered 11/1, 2016 at 15:54 Comment(1)
This worked for me, the accepted answer did not. Working with a Border in a Grid with WPF in .NET Framework 4.5.2.Ola
C
5

Taking into account a few suggestions i found here this solved the problem for me.

item.TransformToVisual( relativeToElement )
    .TransformBounds( new Rect( item.RenderSize ) );
Cyanite answered 8/1, 2018 at 10:54 Comment(0)
O
1

Nevermind, I finally managed to figure it out using a combination of LayoutInformation.GetLayoutSlot() (although I probably could have used either ActualWidth/ActualHeight or RenderSize) and UIElement.TranslatePoint().

Seems a rather complicated solution when it could be as simple as this:

myElement.GetBounds( relativeElement );

Oh well. Maybe time for an extension method. :)

Overstay answered 12/8, 2010 at 22:23 Comment(4)
I was saying there should be.Overstay
Would you please show the complete solution? I didn't get it to work. It was always wrong relative to some parent element. For now, I'm converting everything to screen coordinates with myElement.PointToScreen(new Point()) which is okay for handling WM_NCHITTEST. But I still consider it a hack.Shakira
We all are happy that you solved your problem. Please provide us your solution here.Oscillograph
@Oscillograph Sorry I haven't done .NET development in some time. I suggest reading the documentation for TranslatePoint.Overstay

© 2022 - 2024 — McMap. All rights reserved.