当孩子滚动到视野中时是否会引发一个事件,并指出孩子被实现了什么?
当然有ScrollChanged事件,但它没有向我提供任何关于滚动到视图中的元素的指示。
提前致谢。
编辑:
Iv'e尝试连接到ScrollViewer的RequestBringIntoView事件,但它永远不会到达。或者,我也在包含这些项目的StackPanel上尝试了相同的操作:
XAML :
<ScrollViewer RequestBringIntoView="ScrollViewer_RequestBringIntoView" >
<StackPanel RequestBringIntoView="StackPanel_RequestBringIntoView">
<Button Content="1" Height="20"/>
<Button Content="2" Height="20"/>
<Button Content="3" Height="20"/>
<Button Content="4" Height="20"/>
<Button Content="5" Height="20"/>
<Button Content="6" Height="20"/>
<Button Content="7" Height="20"/>
<Button Content="8" Height="20"/>
<Button Content="9" Height="20"/>
<Button Content="10" Height="20"/>
<Button Content="11" Height="20"/>
<Button Content="12" Height="20"/>
<Button Content="13" Height="20"/>
<Button Content="14" Height="20"/>
<Button Content="15" Height="20"/>
<Button Content="16" Height="20"/>
<Button Content="17" Height="20"/>
<Button Content="18" Height="20"/>
<Button Content="19" Height="20"/>
<Button Content="20" Height="20"/>
<Button Content="21" Height="20"/>
<Button Content="22" Height="20"/>
<Button Content="23" Height="20"/>
<Button Content="24" Height="20"/>
</StackPanel>
</ScrollViewer>
他们永远不会到达。据我所知,ScrollViewer在其封装的子元素上调用BringIntoView,并且它们引发了RequestBringIntoView事件,我希望它会在可视化树上传播。我想ScrollViewer会在内部处理该事件。所以我最终遇到了如何在孩子被带入视野时获得通知的相同问题。我可以挂钩他们每个人或者也许一个ItemsControl会为我做那个..?
答案 0 :(得分:6)
我认为你应该看看this article,它可以告诉观众控件是否对观众可见。
如果您要在ScrollChanged处理程序中挂接对该自定义方法的调用,因此每次滚动时都会检查,我认为这样做会有所帮助。我会自己尝试一下......
编辑:它有效!这是方法:
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)
{
// Your logic
}
}
}
}
编辑:我从dev hedgehog发布的链接中查看了ScrollViewer的源代码,发现了这个有趣的私有函数:
// Returns true only if element is partly visible in the current viewport
private bool IsInViewport(ScrollContentPresenter scp, DependencyObject element)
{
Rect viewPortRect = KeyboardNavigation.GetRectangle(scp);
Rect elementRect = KeyboardNavigation.GetRectangle(element);
return viewPortRect.IntersectsWith(elementRect);
}
这显然表明,即使ScrollViewer本身也有兴趣知道什么是可见的,并且正如我预期的那样,基本上执行与辅助方法相同的计算。下载此代码并查看谁调用此方法,其中和原因可能是值得的。
编辑:看起来像是由OnKeyDown()调用并用于确定焦点行为,就是这样。有趣....
答案 1 :(得分:2)
新编辑:我再次阅读了您的问题,我意识到我一开始并不了解您。
抱歉,我认为您的意思是,当您将鼠标放在里面时,或者在第一个可见或最后一个可见项目之间设置焦点时,您希望通知ScrollViewer的视口中的孩子。这就是RequestBringIntoView派上用场的时候。
还有一些事情我不清楚:
“当孩子滚动到视野中时,是否会出现一个事件,表明孩子被实现了什么?” - 你在谈论普通面板还是VirtualizingStackPanel?
答案ouflak张贴的设计都不错。实际上通常是WPF。
如果您仍然没有考虑我们的建议,请查看ScrollViewer的源代码。
也许你会偶然发现你可以使用的事件。
旧编辑:这就是您要找的。 p>
http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.requestbringintoview.aspx
答案 2 :(得分:1)
好的,另一个答案是不同的,但基于dev hedgehog's的建议。基本上这个想法是项目的BringIntoView方法在实际处于视图中时总是被调用。如何确定这一点有点神秘,如果将两个项目滚动到视图中会发生什么是未知的。但是一些示例代码应该捕获BringIntoView的所有调用:
string guid = System.Guid.NewGuid().ToString();
RoutedEvent scrollIntoViewEvent = EventManager.RegisterRoutedEvent(
guid,
RoutingStrategy.Direct,
typeof(RequestBringIntoViewEventHandler),
typeof(ScrollViewer));
EventManager.RegisterClassHandler(typeof(ScrollViewer), scrollIntoViewEvent, new RequestBringIntoViewEventHandler(this.RequestBringIntoView_Handler), true);
一个示例处理程序:
private void RequestBringIntoView_Handler(object sender, RequestBringIntoViewEventArgs e)
{
Object o = sender;
}
这里的一些推文可能只是为了捕获所有BringIntoView事件,这应该为原始问题提供解决方案,因为此处理程序确实将项目传递给发件人。