ScrollViewer - Indication of child element scrolled into view

后端 未结 3 592
孤街浪徒
孤街浪徒 2021-01-01 07:35

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

Of course there is the ScrollChanged event, b

3条回答
  •  萌比男神i
    2021-01-01 08:08

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

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

    Edit: It works! Here's the method:

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

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

    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.

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

提交回复
热议问题