Obtener la posición absoluta del elemento dentro de la ventana en wpf


88

Me gustaría obtener la posición absoluta de un elemento en relación con la ventana / elemento raíz cuando se hace doble clic en él. La posición relativa del elemento dentro de su padre es todo a lo que puedo llegar, y lo que estoy tratando de alcanzar es el punto relativo a la ventana. He visto soluciones sobre cómo obtener el punto de un elemento en la pantalla, pero no en la ventana.

Respuestas:


127

Creo que lo que BrandonS quiere no es la posición del mouse en relación con el elemento raíz, sino la posición de algún elemento descendiente.

Para eso, existe el método TransformToAncestor :

Point relativePoint = myVisual.TransformToAncestor(rootVisual)
                              .Transform(new Point(0, 0));

¿Dónde myVisualestá el elemento en el que se acaba de hacer doble clic, y rootVisuales Application.Current.MainWindow o lo que sea que desee la posición relativa.


2
Hola, probé esto y obtengo la siguiente excepción: System.InvalidOperationException no se manejó Mensaje = El Visual especificado no es un antepasado de este Visual. Fuente = PresentationCore ¿Alguna idea?
RoflcoptrException

8
Visual.TransformToAncestor solo funcionará si pasa un Visual. Si desea la posición relativa de dos elementos y uno no contiene al otro, puede usar Visual.TransformToVisual en su lugar.
Robert Macnee

5
TransformToVisual aún requiere un ancestro común que puede ser problemático si el control está en una ventana emergente
Adam Mills

1
¡Súper intuitivo! ¿No pueden envolver esto en una llamada "GetRelativePosition"? :-) Gracias por la ayuda. +1
Paul

1
@ cod3monk3y - o quizás, tal vez si Microsoft abre las fuentes WPF, les enviaré una solicitud de extracción :-)
Paul

41

Para obtener la posición absoluta de un elemento de la interfaz de usuario dentro de la ventana, puede usar:

Point position = desiredElement.PointToScreen(new Point(0d, 0d));

Si está dentro de un control de usuario y simplemente desea la posición relativa del elemento de la interfaz de usuario dentro de ese control, simplemente use:

Point position = desiredElement.PointToScreen(new Point(0d, 0d)),
controlPosition = this.PointToScreen(new Point(0d, 0d));

position.X -= controlPosition.X;
position.Y -= controlPosition.Y;

4
Tenga en cuenta que esto probablemente no haga lo que espera si la escala de su pantalla no está configurada al 100% (es decir, en pantallas de DPI alto).
Drew Noakes

18

Agregue este método a una clase estática:

 public static Rect GetAbsolutePlacement(this FrameworkElement element, bool relativeToScreen = false)
    {
        var absolutePos = element.PointToScreen(new System.Windows.Point(0, 0));
        if (relativeToScreen)
        {
            return new Rect(absolutePos.X, absolutePos.Y, element.ActualWidth, element.ActualHeight);
        }
        var posMW = Application.Current.MainWindow.PointToScreen(new System.Windows.Point(0, 0));
        absolutePos = new System.Windows.Point(absolutePos.X - posMW.X, absolutePos.Y - posMW.Y);
        return new Rect(absolutePos.X, absolutePos.Y, element.ActualWidth, element.ActualHeight);
    }

Configure el relativeToScreenparámetro en truepara colocarlo desde la esquina superior izquierda de toda la pantalla o en falsepara colocarlo en la esquina superior izquierda de la ventana de la aplicación.


1
¡Esto funciona fantásticamente! Estoy usando esto con una animación que desliza una imagen dentro o fuera de la pantalla modificando la RenderTransformdel elemento y, por lo tanto, necesita saber la posición absoluta del elemento en la pantalla.
cod3monk3y

6

Desde .NET 3.0, simplemente puede usar *yourElement*.TranslatePoint(new Point(0, 0), *theContainerOfYourChoice*).

Esto le dará el punto 0, 0 de su botón, pero hacia el contenedor. (También puede dar otro punto que 0, 0)

Consulte aquí el documento.


0

Hm. Tienes que especificar la ventana en la que hiciste clic en El Mouse.GetPosition(IInputElement relativeTo) siguiente código funciona bien para mí

protected override void OnMouseDown(MouseButtonEventArgs e)
    {
        base.OnMouseDown(e);
        Point p = e.GetPosition(this);
    }

Sospecho que necesita hacer referencia a la ventana no desde su propia clase sino desde otro punto de la aplicación. En este caso Application.Current.MainWindowte ayudará.


Aunque no es lo que pidió el autor, me puso en el camino correcto, gracias
Ladislav Ondris
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.