2009-03-20 17 views
12

Tengo una colección de Visual s en un ListBox. Necesito encontrar el XPosition de un elemento dentro de él y luego animar el HorizontalOffset del ListBox 's ScrollViewer. Esencialmente quiero crear un método animado ScrollIntoView.WPF - Animate ListBox.ScrollViewer.HorizontalOffset?

Esto me da un par de problemas. En primer lugar, ¿cómo puedo obtener una referencia al visualizador de desplazamiento ListBox? En segundo lugar, ¿cómo puedo obtener el relativo XPosition o HozintalOfffset de un elemento arbitrario en el ListBox?

No estoy respondiendo a ninguna entrada en el ListBox sí mismo así que no puedo usar Mouse propiedades relacionadas.

Respuesta

32

No creo que pueda usar un guión gráfico WPF para la animación porque los guiones gráficos animan las propiedades de dependencia de WPF. Tendrá que llamar al ScrollViewer.ScrollToHorizontalOffset(double) para desplazarse.

Puede intentar crear una propiedad de dependencia personalizada que llame a SetHorizontalOffset en la función OnDependencyPropertyChanged(). Entonces podrías animar esta propiedad.

public static readonly DependencyProperty ScrollOffsetProperty = 
    DependencyProperty.Register("ScrollOffset", typeof(double), typeof(YOUR_TYPE), 
    new FrameworkPropertyMetadata(0.0, new PropertyChangedCallback(OnScrollOffsetChanged))); 


public double ScrollOffset 
{ 
    get { return (double)GetValue(ScrollOffsetProperty); } 
    set { SetValue(ScrollOffsetProperty, value); } 
} 

private static void OnScrollOffsetChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) 
{ 
    YOUR_TYPE myObj = obj as YOUR_TYPE; 

    if (myObj != null) 
     myObj.SCROLL_VIEWER.ScrollToHorizontalOffset(myObj.ScrollOffset); 
} 

Para obtener el visor de desplazamiento se puede utilizar el VisualTreeHelper a buscar a los niños visuales del cuadro de lista. Guarde una referencia al ScrollViewer porque lo necesitará más adelante. Pruebe esto:

public static childItem FindVisualChild<childItem>(DependencyObject obj) 
    where childItem : DependencyObject 
{ 
    // Iterate through all immediate children 
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) 
    { 
     DependencyObject child = VisualTreeHelper.GetChild(obj, i); 

     if (child != null && child is childItem) 
     return (childItem)child; 

     else 
     { 
     childItem childOfChild = FindVisualChild<childItem>(child); 

     if (childOfChild != null) 
      return childOfChild; 
     } 
    } 

    return null; 
} 

Esta función devuelve el primer elemento secundario visual del tipo de parámetro. Llame al FindVisualChild<ScrollViewer>(ListBox) para obtener el ScrollViewer.

Por último, intente utilizar UIElement.TranslatePoint(Point, UIElement) para obtener la posición X del artículo. Llame a esta función en el artículo, pase 0,0 para el punto y pase el ScrollViewer.

Espero que esto ayude.

+0

Mi Señor, ¡eso es un trabajo! Gracias por la ayuda, Josh, me ha señalado al menos en la dirección correcta. – Stimul8d

+0

¿Quiere decir ScrollToHorizontalOffset en lugar de SetHorizontalOffset? –

+0

Sí, tienes razón. ¡Gracias! –

1

No estoy seguro si mi método es una buena práctica, pero por el tiempo limitado que tuve, pareció funcionar bien. En vez de usar un storyboard, acabo de utilizar un DispatcherTimer.

ScrollLeftButtonCommand = new DelegateCommand(
    o => 
     { 
      var scrollViewer = (ScrollViewer)o; 

      scrollTimer = new DispatcherTimer(); 

      scrollTimer.Start(); 

      scrollTimer.Interval = TimeSpan.FromMilliseconds(30); 

      scrollTimer.Tick += (s, e) => 
      {   
       scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset - 50); 

       if (scrollViewer.HorizontalOffset <= 0) 
       { 
        scrollTimer.Stop(); 
       } 
      }; 
     }); 

Asegúrese de que sea un DispatchTimer modo que el hilo es capaz de tomar el control del elemento de interfaz de usuario

Asimismo, recuerda a unirse a su objeto en su vista!

<Button CommandParameter="{Binding ElementName=MyScrollViewer }" 
     Command="{Binding ScrollLeftButtonCommand }"/>