假设我想这样做,所以我可以找到鼠标相对于Visual
的当前位置,而无需访问特定的鼠标事件:
public static Point GetMousePosition(this Visual relativeTo)
{
return relativeTo.PointFromScreen(GetMousePositionOnScreen());
}
有时(通常当我刚刚在两个标签控件之间切换时)PointFromScreen
会抛出InvalidOperationException
消息此Visual未连接到PresentationSource。
查看Visual
上可用的属性时,我看不到任何与PresentationSource
相关的内容。
给定Visual
,当我在其上调用PointFromScreen
时,如何判断它是否会抛出该异常?
答案 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)
可能会发生异常,因为视觉被丢弃但由于内存泄漏仍在内存中。
我遇到了类似的问题。我发现异常发生在视觉上,应该是垃圾收集。修复视觉中的内存泄漏解决了问题。