您可以使用 Lester 的 WPF\SL 博客上的 Determining the Visibility of Elements inside ScrollViewer 文章中的方法来确定特定项目是否在 ScrollViewer 中可见。来自该博客:
// position of your visual inside the scrollviewer
GeneralTransform childTransform = ContainedObject.TransformToAncestor(ScrollViewerObj);
Rect rectangle = childTransform.TransformBounds(new Rect(new Point(0,0),
ContainedObject.RenderSize));
// Check if the elements Rect intersects with that of the scrollviewer's
Rect result = Rect.Intersect(new Rect(new Point(0, 0), ScrollViewerObj.RenderSize),
rectangle);
// if result is Empty then the element is not in view
if (result == Rect.Empty)
{
ContainedObject.IsPopupOpen = false; // <<< Close relevant popup here
}
else
{
//obj is partially Or completely visible
//skip or bring obj in view.
}
显然,要使其工作,您需要将新的bool IsPopupOpen 属性添加到数据绑定到TextBox.Text 属性的数据对象中。然后,您也需要将 Bind 这个 Popup.IsOpen 属性:
<Popup IsOpen="{Binding IsPopupOpen}" StaysOpen="False" ... />
更新>>>
ScrollViewer.ScrollChanged 事件会在 ScrollViewer 滚动时经常被调用。直接在该事件处理程序中执行任何代码确实是不明智的,但是 ScrollChangedEventArgs 对象具有一些可以帮助我们的属性。请查看 MSDN 上的 ScrollChangedEventArgs Class 页面,了解这些属性的完整详细信息。
您可以在名为VerticalChange 和HorizontalChange 的事件处理程序中访问两个属性,它们应该会显示自上次事件以来ScrollViewer 滚动了多少。 [现在已经有一段时间了,所以我不能保证它们是正确的属性,但是如果您在事件处理程序中使用 MSDN 上 ScrollChangedEventArgs.VerticalChange Property 页面中的示例代码,读出的内容应该会给您一个线索哪些是要使用的正确属性。]
因此,找到相关属性后,您可以在处理程序中使用它们来确定是否执行您的代码...尝试以下操作:
double totalVerticalChange = 0.0;
double minimumValue = 24.0; // set this to whatever you want as a minimum scroll value
...
private void ScrollViewer_Changed(object sender, ScrollChangedEventArgs e)
{
if (totalVerticalChange + e.VerticalChange >= minimumValue)
{
totalVerticalChange = 0.0;
// perform your functionality here
}
else totalVerticalChange += e.VerticalChange;
}
如果这里有错误,请原谅我,因为我目前无法在 Visual Studio 中检查这一点,但希望你能明白……本质上,这就像我们正在“过滤”掉一些事件。