2010-01-28 8 views
12

supongamos que se quiere hacer esto, así que se puede encontrar la posición actual del ratón con relación a un Visual, sin necesidad de acceder a un evento de ratón específico:En WPF, ¿bajo qué circunstancias Visual.PointFromScreen lanza InvalidOperationException?

public static Point GetMousePosition(this Visual relativeTo) 
{ 
    return relativeTo.PointFromScreen(GetMousePositionOnScreen()); 
} 

veces (por lo general cuando he acabo de cambiar entre dos controles de pestañas) PointFromScreen arroja un InvalidOperationException con el mensaje Este Visual no está conectado a un PresentationSource.

Al ver las propiedades disponibles en Visual No puedo ver ninguno en relación con PresentationSource.

Dado un Visual, ¿cómo puedo saber si arrojará esa excepción cuando llamo al PointFromScreen en él?

Respuesta

19

Hay un método estático PresentationSource.FromVisual cuales:

Devuelve la fuente en la que un dotado visual se presenta.

Sé que esto no resuelve el problema subyacente, pero puede comprobar que el Visual esté conectado a un PresentationSource antes de llamar al PointFromScreen. Evitaría la excepción, pero necesitaría investigar un poco más por qué no estaba conectado en primer lugar.

+0

Es cierto: estoy usando un temporizador. Ocasionalmente, el temporizador se dispara cuando Visual no está en buen estado. Puedo ignorar el temporizador con seguridad si eso ocurre. le daré una oportunidad. –

3

Tuve un problema similar con una visual personalizada.

La solución fue aplazar la tarea problemática a través de Dispatcher (ejecución diferida con prioridad fondo en este caso) ...

public void MyProblematicDisplayMethod(Symbol TargetSymbol) 
{ 
    this.HostingScrollViewer.BringIntoView(TargetSymbol.HeadingContentArea); 
    ... 
    // This post-call is needed due to WPF tricky rendering precedence (or whatever it is!). 
    this.HostingScrollViewer.PostCall(
     (scrollviewer) => 
     { 
      // in this case the "scrollviewer" lambda parameter is not needed 
      var Location = TargetSymbol.Graphic.PointToScreen(new Point(TargetSymbol.HeadingContentArea.Left, TargetSymbol.HeadingContentArea.Top)); 
      ShowOnTop(this.EditBox, Location); 
      this.EditBox.SelectAll(); 
     }); 
    ... 
} 

/// <summary> 
/// Calls, for this Source object thread-dispatcher, the supplied operation with background priority (plus passing the source to the operation). 
/// </summary> 
public static void PostCall<TSource>(this TSource Source, Action<TSource> Operation) where TSource : DispatcherObject 
{ 
    Source.Dispatcher.BeginInvoke(DispatcherPriority.Background, 
     new DispatcherOperationCallback(delegate(Object state) 
             { Operation(Source); return null; }), 
     null); 
} 

que he usado que PostCall en otras situaciones relacionadas representación ScrollViewer.

+0

Oh sí, tengo que hacer tanto en WPF que tengo un método de ayuda similar, quizás todo el mundo lo haga ... –

1

Tarde para el juego de pelota, pero estas respuestas me ayudaron. Solo quería señalar que PresentaionSources no están conectados a elementos visuales hasta que estén completamente cargados. Entonces, si en su constructor está configurando eventos que pueden dispararse antes de que el elemento visual al que está tratando de llamar PointFromScreen esté listo para mostrarse en la pantalla, entonces obtendrá ese error. Aunque como se mencionó antes de que pueda envolver su método en algo así como:

public static Point GetMousePosition(this Visual relativeTo) 
{ 
    if(PresentationSource.FromVisual(relativeTo) != null) 
     return relativeTo.PointFromScreen(GetMousePositionOnScreen()); 
    else 
     return new Point(); 
} 

usted podría también no considere llamar a su método hasta que esté seguro de que lo visual ha sido rinde en pantalla al menos una vez.

+0

No puede devolver nulo porque Point es un tipo de valor que no admite nulos. Es posible que desee devolver algo como "devolver nuevo punto()" – dontbyteme

1

La excepción se puede producir debido a que una imagen visual se descarta pero aún se encuentra en la memoria debido a una pérdida de memoria.

Estaba teniendo un problema similar. Encontré la excepción que ocurre en un visual que se suponía que era basura. La solución de las pérdidas de memoria en el visual resolvió el problema.

+0

cómo se corrigió la pérdida de memoria? – user5944566

+0

Utilicé una herramienta para encontrar y corregir las fugas. Puede usar cualquiera de las muchas herramientas, p. dotMemory, memprofiler. –

2

He encontrado que puedes probar IsVisible antes de llamar al PointFromScreen para protegerte contra el InvalidOperationException.

Cuestiones relacionadas