在WPF中,Visual.PointFromScreen在什么情况下抛出InvalidOperationException?

时间:2010-01-28 11:50:22

标签: wpf .net-3.5

假设我想这样做,所以我可以找到鼠标相对于Visual的当前位置,而无需访问特定的鼠标事件:

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

有时(通常当我刚刚在两个标签控件之间切换时)PointFromScreen会抛出InvalidOperationException消息此Visual未连接到PresentationSource。

查看Visual上可用的属性时,我看不到任何与PresentationSource相关的内容。

给定Visual,当我在其上调用PointFromScreen时,如何判断它是否会抛出该异常?

5 个答案:

答案 0 :(得分:22)

有一个静态方法PresentationSource.FromVisual

  

返回提供Visual的源。

我知道这不能解决根本问题,但您可以在调用PointFromScreen之前检查Visual是否已连接到PresentationSource。它可以防止异常,但你需要做一些调查,看看为什么它首先没有连接。

答案 1 :(得分:3)

我在定制视觉方面遇到了类似的问题。

解决方案是通过Dispatcher延迟有问题的任务(在这种情况下延迟执行具有后台优先级)...

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

我在其他与ScrollViewer相关的渲染情况中使用了PostCall。

答案 2 :(得分:3)

我发现您可以在致电CheckBox之前测试IsVisible以防范PointFromScreen

答案 3 :(得分:2)

赛后期,但这些回应对我有所帮助。我只是想指出,在完全加载之前,PresentaionSources没有连接到可视元素。因此,如果在您的构造函数中设置可能在您尝试调用PointFromScreen的可视元素之前触发的事件已准备好显示在屏幕上,那么您将收到该错误。如前所述,您可以将方法包装为:

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

在确定视觉已在屏幕上呈现至少一次之前,您还可以考虑不调用您的方法。

答案 4 :(得分:1)

可能会发生异常,因为视觉被丢弃但由于内存泄漏仍在内存中。

我遇到了类似的问题。我发现异常发生在视觉上,应该是垃圾收集。修复视觉中的内存泄漏解决了问题。