【问题标题】:How to scroll to element in UWP如何滚动到 UWP 中的元素
【发布时间】:2015-11-18 08:16:57
【问题描述】:

如何滚动到滚动查看器中的特定位置?

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

我正在尝试滚动到我的滚动查看器中的特定元素,但我是 UWP 的新手,我不太明白如何去做。

我想在事件发生时在第二个文本块中设置 MyScrollView 的滚动位置。

【问题讨论】:

    标签: c# uwp


    【解决方案1】:

    更好的解决方案是使用 ChangeView 而不是 ScrollToVerticalOffset/ScrollToHorizontalOffset,因为后者在 Windows 10 中已过时。

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

    您甚至可以通过将最后一个参数设置为false启用滚动动画。


    更新

    为了完整起见,我为此创建了一个扩展方法。

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

    所以在这种情况下,只需要调用

    this.MyScrollView.ScrollToElement(otherTb);
    

    【讨论】:

    • 应该是MyScrollView.ChangeView(null,abosulatePosition.Y,null,true);
    【解决方案2】:

    我找到了答案

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

    更新

    在 UWP 中,ScrollToVerticalOffset 已经过时了,所以

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

    应改为使用。 https://msdn.microsoft.com/en-us/library/windows/apps/dn252763.aspx

    【讨论】:

      【解决方案3】:

      这是下面描述的方法的Video demo,已实现。

      我曾经使用ScrollViewerOffsetMediator,这是一种扩展方法,它依赖于 ScrollToVerticalOffset 方法来平滑地为 ScrollViewer 内容的滚动设置动画。但是,ScrollToVerticalOffset 在 Windows 10 中已被弃用,尽管它在 Windows 10 的某些早期版本中有效,但不再有效。

      新的 ChangeView 方法提供 ScrollViewer 内容的平滑或可控动画。所以这是我找到的解决方案:

      在 ScrollViewer 中放置一个 Grid。使用 RenderTransform 为网格的内容设置动画。在通过转换设置网格内容的动画时,使用新的 ChangeView 方法设置 final 所需的垂直和水平 ScrollViewer 位置。并且在您的网格转换中,将 initial 值偏移 final 所需的 ChangeView 偏移量,以便为由 ChangeView 引起的立即跳转校正动画开始参考方法。

      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>
      

      代码:

      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
      

      例子:

              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)
      

      在这个例子中,无论 ScrollView 的初始垂直位置是什么,内容都会平滑地动画到一个固定的垂直位置并缩放。

      【讨论】:

        猜你喜欢
        • 2010-10-04
        • 1970-01-01
        • 1970-01-01
        • 2019-12-25
        • 1970-01-01
        • 1970-01-01
        • 2010-10-12
        • 2017-09-12
        • 2019-10-08
        相关资源
        最近更新 更多