c# - visual - Cómo desplazarse a un elemento en UWP
uwp vs wpf (3)
¿Cómo puedo desplazarme a una posición específica dentro de un 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>
Estoy intentando desplazarme a un elemento específico en mi scrollviewer pero soy nuevo en UWP y no puedo entender bien cómo hacerlo.
Quiero establecer la posición de desplazamiento de MyScrollView en el segundo bloque de texto en un evento que está sucediendo.
Encontré la respuesta
var transform = otherTb.TransformToVisual(ContentsPanel);
Point absolutePosition = transform.TransformPoint(new Point(0,0));
MyScrollView.ScrollToVerticalOffset(absolutePosition.Y);
Actualizar
En UWP ScrollToVerticalOffset está obsoleto por lo
MyScrollView.ChangeView(null,absolutePosition.Y,null,true)
debería usarse en su lugar. https://msdn.microsoft.com/en-us/library/windows/apps/dn252763.aspx
Una mejor solución es usar ChangeView
lugar de ScrollToVerticalOffset
/ ScrollToHorizontalOffset
ya que este último es obsoleto en Windows 10.
MyScrollView.ChangeView(null, abosulatePosition.Y, null, true);
Incluso puede habilitar la animación de desplazamiento estableciendo el último parámetro en false
.
Actualizar
Por el bien de completarlo, he creado un método de extensión para esto.
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);
}
}
Entonces, en este caso, solo necesita llamar
this.MyScrollView.ScrollToElement(otherTb);
Solía usar ScrollViewerOffsetMediator , un método de extensión que dependía del método ScrollToVerticalOffset para animar suavemente el desplazamiento del contenido de ScrollViewer. Sin embargo, ScrollToVerticalOffset ha quedado obsoleto en Windows 10, y aunque funcionó en algunas versiones anteriores de Windows 10, ya no funciona.
El nuevo método ChangeView no proporciona animación uniforme ni controlable del contenido de ScrollViewer. Así que aquí está la solución que he encontrado:
Coloque una cuadrícula dentro del ScrollViewer. Anima los contenidos de la grilla usando RenderTransform. Utilice el nuevo método ChangeView para establecer sus posiciones finales de desplazamiento vertical y horizontal deseadas en el momento en que configura su animación de los contenidos de la grilla a través de la transformación. Y en su transformación de cuadrícula, desplace los valores iniciales por el desplazamiento final ChangeView deseado, de modo que la referencia de inicio de la animación se corrija para el salto inmediato que será causado por el método 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>
Código:
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
Ejemplo:
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)
En este ejemplo, no importa cuál sea la posición vertical inicial del ScrollView, el contenido se animará suavemente a una posición vertical fija y a un zoom.