ScrollViewer - 指示子元素滚动到视图中 [英] ScrollViewer - Indication of child element scrolled into view

查看:83
本文介绍了ScrollViewer - 指示子元素滚动到视图中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有在孩子滚动到视图中时引发的事件并指示实现了什么孩子?

Is there an event that is raised when a child is scrolled into view and gives an indication of what child was realized?

当然有 ScrollChanged 事件,但它没有向我提供任何关于滚动到视图中的元素的指示.

Of course there is the ScrollChanged event, but it does not provide me with any indication of what element was scrolled into view.

提前致谢.

我曾尝试连接到 ScrollViewer 的 RequestBringIntoView 事件,但从未达到.或者,我也在包含项目的 StackPanel 上尝试了同样的方法:

Iv'e tried hooking up to the ScrollViewer's RequestBringIntoView Event, but it is never reached. Alternatively I also tried the same on the StackPanel containing the items as such:

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 会为我做这件事..?

They are never reached. As I understand it, the ScrollViewer calls BringIntoView on it's encapsulated child elements and they raise the RequestBringIntoView event, which I would expect to propagate up the visual tree. I guess the ScrollViewer handles that event internally. So I end up with the same problem of how to get notified when it's child is brought into view. I could hook each of them up or maybe an ItemsControl would do that for me..?

推荐答案

我觉得你应该看看 这篇文章 提供了一种判断控件是否对查看者可见的方法.

I think you should look at this article which gives a way of telling if a control is visible to the viewer.

如果您要在 ScrollChanged 处理程序中调用该自定义方法,从而在每次滚动时都进行检查,我认为这可以解决问题.我会自己试试这个......

If you were to hook up a call to that custom method in your ScrollChanged handler, thus having a checked every time you scrolled, I think that would do the trick. I'll try this out myself....

它有效!方法如下:

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

还有我的简单代码调用:

And my simple code call:

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

我从开发刺猬发布的链接中查看了 ScrollViewer 的源代码,发现了这个有趣的私有函数:

I took a look through the source code of the ScrollViewer from the link that dev hedgehog posted and found this interesting private function:

// 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 本身也有兴趣知道什么是可见的,并且正如我所预期的那样,基本上执行与该辅助方法相同类型的计算.下载此代码并查看调用此方法、在哪里以及为什么调用此方法可能是值得的.

This obviously suggests that even the ScrollViewer itself is interested in knowing what's visible and, as I expected, essentially performs the same kind of calculation as in that helper method. It might be worthwhile to download this code and see who calls this method, where, and why.

看起来它被 OnKeyDown() 调用并用于确定焦点行为,仅此而已.有趣....

Looks like its called by OnKeyDown() and used to determine focus behavior, and that's it. Interesting....

这篇关于ScrollViewer - 指示子元素滚动到视图中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆