简体   繁体   English

如何滚动到UWP中的元素

[英]How to scroll to element in UWP

How can I scroll to specific position inside a scrollviewer? 如何滚动到滚动查看器中的特定位置?

 <ScrollViewer x:Name ="MyScrollView" HorizontalScrollBarVisibility="Hidden" Height="500">                      
   <StackPanel x:Name="ContentsPanel">
        <TextBlock x:Name="someTb" Height="50">
        </TextBlock>
        <TextBlock x:Name="otherTb" Height="100">
        </TextBlock>
   </StackPanel>
</ScrollViewer>

I am trying to scroll to a specific element in my scrollviewer but I am new to UWP and I can't quite get it right how to do it. 我正在尝试滚动到我的滚动查看器中的特定元素,但我是UWP的新手,我无法完全理解如何做到这一点。

I want to set the scroll position of MyScrollView in the second textblock on an event happening. 我想在事件发生时在第二个文本块中设置MyScrollView的滚动位置。

A better solution is to use ChangeView instead of ScrollToVerticalOffset / ScrollToHorizontalOffset since the latter is obsolete in Windows 10. 更好的解决方案是使用ChangeView而不是ScrollToVerticalOffset / ScrollToHorizontalOffset因为后者在Windows 10中已过时。

MyScrollView.ChangeView(null, abosulatePosition.Y, null, true);

You can even enable scrolling animation by setting the last parameter to false . 您甚至可以通过将最后一个参数设置为false启用滚动动画。


Update 更新

For the sake of completion, I've created an extension method for this. 为了完成,我为此创建了一个扩展方法。

public static void ScrollToElement(this ScrollViewer scrollViewer, UIElement element, 
    bool isVerticalScrolling = true, bool smoothScrolling = true, float? zoomFactor = null)
{
    var transform = element.TransformToVisual((UIElement)scrollViewer.Content);
    var position = transform.TransformPoint(new Point(0, 0));

    if (isVerticalScrolling)
    {
        scrollViewer.ChangeView(null, position.Y, zoomFactor, !smoothScrolling);
    }
    else
    {
        scrollViewer.ChangeView(position.X, null, zoomFactor, !smoothScrolling);
    }
}

So in this case, just need to call 所以在这种情况下,只需要打电话

this.MyScrollView.ScrollToElement(otherTb);

I found the answer 我找到了答案

    var transform = otherTb.TransformToVisual(ContentsPanel);
    Point absolutePosition = transform.TransformPoint(new Point(0,0));
    MyScrollView.ScrollToVerticalOffset(absolutePosition.Y);

Update 更新

In UWP ScrollToVerticalOffset is obsolete so 在UWP中,ScrollToVerticalOffset已经过时了

    MyScrollView.ChangeView(null,absolutePosition.Y,null,true)

should be used instead. 应该用来代替。 https://msdn.microsoft.com/en-us/library/windows/apps/dn252763.aspx https://msdn.microsoft.com/en-us/library/windows/apps/dn252763.aspx

Here is a Video demo of the method described below, implemented. 以下是实施的下述方法的视频演示

I used to use the ScrollViewerOffsetMediator , an extension method which relied upon the ScrollToVerticalOffset method to smoothly animate scrolling of the ScrollViewer contents. 我曾经使用ScrollViewerOffsetMediator ,这是一种依赖ScrollToVerticalOffset方法的扩展方法,可以平滑地动画滚动ScrollViewer内容。 However, ScrollToVerticalOffset has been deprecated in Windows 10, and although it worked in some earlier releases of Windows 10, it no longer does. 但是,ScrollToVerticalOffset在Windows 10中已被弃用,尽管它在某些早期版本的Windows 10中有效,但它不再适用。

The new ChangeView method does not provide either smooth nor controllable animation of the ScrollViewer contents. 新ChangeView方法提供的内容的ScrollViewer任一光滑也不可控动画。 So here is the solution that I've found: 所以这是我找到的解决方案:

Place a Grid within the ScrollViewer. 在ScrollViewer中放置一个Grid。 Animate the contents of the grid using a RenderTransform. 使用RenderTransform为网格内容设置动画。 Use the new ChangeView method to set your final desired vertical and horizontal ScrollViewer positions at the time you set up your animation of the grid contents via the transformation. 使用新的ChangeView方法在通过转换设置网格内容动画时设置最终所需的垂直和水平ScrollViewer位置。 And in your grid transformation, offset the initial values by the final desired ChangeView offset, so that the animation start reference is corrected for the immediate jump that will be caused by the ChangeView method. 在网格转换中,将初始值偏移最终所需的ChangeView偏移量,以便针对由ChangeView方法引起的即时跳转更正动画开始引用。

XAML: XAML:

         <ScrollViewer x:Name="MyScrollView">
            <Grid Name="MyGrid">
                <Grid.RenderTransform>
                    <TransformGroup>
                        <ScaleTransform ScaleX="1" ScaleY="1"/>
                        <TranslateTransform X="0" Y="0"/>
                    </TransformGroup>
                </Grid.RenderTransform>
                <!-- Original ScrollViewer Contents Here... -->
            </Grid>
         </ScrollViewer>

Code: 码:

Public Sub AnimateProperty(Obj As DependencyObject, PropPath As String, StartValue As Double, EndValue As Double, Optional PeriodMS As Integer = 350)

    Dim Storya As New Storyboard

    Dim DA1 As New DoubleAnimationUsingKeyFrames With {.BeginTime = New TimeSpan(0, 0, 0)}

    Storyboard.SetTarget(DA1, Obj)
    Storyboard.SetTargetProperty(DA1, PropPath)


    Dim ddkf1 As New DiscreteDoubleKeyFrame With {.KeyTime = New TimeSpan(0, 0, 0), .Value = StartValue}
    Dim edkf1 As New EasingDoubleKeyFrame With {.Value = EndValue, .KeyTime = New TimeSpan(0, 0, 0, 0, PeriodMS)}

    Dim pe1 As New PowerEase With {.EasingMode = EasingMode.EaseIn}
    edkf1.EasingFunction = pe1


    DA1.KeyFrames.Add(ddkf1)
    DA1.KeyFrames.Add(edkf1)

    Storya.Children.Add(DA1)
    Storya.Begin()

End Sub

Example: 例:

        AnimateProperty(MyGrid, "(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)", 1, 1.4, 350)
        AnimateProperty(MyGrid, "(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)", 1, 1.4, 350)
        AnimateProperty(MyGrid, "(UIElement.RenderTransform).(TransformGroup.Children)[1].(TranslateTransform.Y)", -MyScrollView.VerticalOffset, -120, 350)
        MyScrollView.ChangeView(Nothing, 0, Nothing, True)

In this example, no matter what the initial vertical position is of the ScrollView, the contents will be smoothly animated to a fixed vertical position and zoom. 在此示例中,无论ScrollView的初始垂直位置是什么,内容都将平滑地动画到固定的垂直位置和缩放。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM