我有一个ScrollViewer
,其中有一个ItemsControl
。 ItemsControl
绑定到ObservableCollection
。 ItemsControl
有一个ItemTemplate
,我在其中提供TextBox
来显示数据。
数据正确显示。我已为每个TextBox
添加了一个弹出窗口,以显示其中展示位置为Top的其他数据。
我面临的问题是当我滚动一个项目不在视图中时,我需要隐藏弹出窗口并在项目出现时再次显示它。
我已订阅了scrollviewer的ScrollChanged
事件,但如何获取超出范围隐藏弹出窗口的项目TextBox
感谢
答案 0 :(得分:3)
您可以使用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" ... />
更新&gt;&gt;&gt;
滚动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中查看此内容,但希望您明白这一点......基本上,就像我们'过滤'了一些事件一样。< / p>
答案 1 :(得分:2)
查看this question here,其中讨论了确定ScrollViewer中对象的可见度。
基本辅助方法:
private bool IsUserVisible(FrameworkElement element, FrameworkElement container)
{
if (!element.IsVisible)
return false;
Rect bounds = element.TransformToAncestor(container).TransformBounds(new Rect(0.0, 0.0, element.ActualWidth, element.ActualHeight));
Rect rect = new Rect(0.0, 0.0, container.ActualWidth, container.ActualHeight);
return rect.Contains(bounds.TopLeft) || rect.Contains(bounds.BottomRight);
}
以及执行您想要执行的操作的示例函数:
private void Scroll_Changed(object sender, ScrollChangedEventArgs e)
{
Object o = sender;
bool elementIsVisible = false;
foreach (FrameworkElement child in this.stackPanel1.Children)
{
if (child != null)
{
elementIsVisible = this.IsUserVisible(child, this.scroller);
if (!elementIsVisible)
{
// Logic to disable popups here...
}
}
}
}