Ottieni la posizione assoluta dell'elemento all'interno della finestra in wpf


88

Vorrei ottenere la posizione assoluta di un elemento rispetto all'elemento window / root quando si fa doppio clic. La posizione relativa dell'elemento all'interno del suo genitore è tutto ciò a cui mi sembra di arrivare, e quello a cui sto cercando di arrivare è il punto relativo alla finestra. Ho visto soluzioni su come ottenere il punto di un elemento sullo schermo, ma non nella finestra.

Risposte:


127

Penso che quello che vuole BrandonS non sia la posizione del mouse rispetto all'elemento radice, ma piuttosto la posizione di qualche elemento discendente.

Per questo, c'è il metodo TransformToAncestor :

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

Dove si myVisualtrova l'elemento su cui è stato appena fatto doppio clic ed rootVisualè Application.Current.MainWindow o qualsiasi altra cosa a cui si desidera la posizione relativa.


2
Ciao, ho provato questo e ottengo la seguente eccezione: System.InvalidOperationException non è stato gestito Message = Il Visual specificato non è un antenato di questo Visual. Fonte = PresentationCore Qualche idea?
RoflcoptrException

8
Visual.TransformToAncestor funzionerà solo se si passa a un oggetto Visual. Se desideri la posizione relativa di due elementi e uno non contiene l'altro, puoi utilizzare Visual.TransformToVisual.
Robert Macnee

5
TransformToVisual richiede ancora un antenato comune che può essere problematico se il controllo è in un popup
Adam Mills

1
Super intuitivo! Non possono racchiudere questo in una chiamata "GetRelativePosition"? :-) Grazie per l'aiuto. +1
Paul

1
@ cod3monk3y - o forse, forse, se Microsoft open source WPF, invierò loro una richiesta pull :-)
Paul

41

Per ottenere la posizione assoluta di un elemento dell'interfaccia utente all'interno della finestra puoi utilizzare:

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

Se ti trovi all'interno di un controllo utente e desideri semplicemente la posizione relativa dell'elemento dell'interfaccia utente all'interno di quel controllo, usa semplicemente:

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

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

4
Nota che questo probabilmente non fa quello che ti aspetti se il ridimensionamento dello schermo non è impostato al 100% (cioè su schermi con DPI alti).
Drew Noakes

18

Aggiungi questo metodo a una classe statica:

 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);
    }

Impostare il relativeToScreenparametro su trueper il posizionamento dall'angolo superiore sinistro dell'intero schermo o su falseper il posizionamento dall'angolo superiore sinistro della finestra dell'applicazione.


1
Funziona in modo fantastico! Lo sto usando con un'animazione che fa scorrere un'immagine sullo schermo o fuori dallo schermo modificando RenderTransforml'elemento dell'elemento, e quindi ha bisogno di conoscere la posizione assoluta dell'elemento sullo schermo.
cod3monk3y

6

A partire da .NET 3.0, puoi semplicemente usare *yourElement*.TranslatePoint(new Point(0, 0), *theContainerOfYourChoice*).

Questo ti darà il punto 0, 0 del tuo pulsante, ma verso il contenitore. (Puoi anche dare un altro punto che 0, 0)

Controlla qui per il doc.


0

Hm. Devi specificare la finestra su cui hai fatto clic in Il Mouse.GetPosition(IInputElement relativeTo) seguente codice funziona bene per me

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

Sospetto che sia necessario fare riferimento alla finestra non dalla propria classe ma da un altro punto dell'applicazione. In questo caso Application.Current.MainWindowti aiuterà.


Anche se non è quello che l'autore ha chiesto, mi ha messo sulla strada giusta, grazie
Ladislav Ondris
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.