2011-08-22 14 views
5

Jak mogę animować przewijanie listBox? Wiem, że mogę używać scrollIntoView, ale jak mogę go animować? Chcę naciskać klawisze strzałek, aby przejść z jednego listBoxItem do drugiego.Animacja przewijania

Odpowiedz

7

Tutaj jest szorstka realizacja opiera się na tym samym podejściu poniższego linku
http://aniscrollviewer.codeplex.com/

Obiekt VerticalOffset jest tylko do odczytu, więc zamiast tego można użyć dołączonego właściwość VerticalOffset na ScrollViewer co z kolei czyni ScrollToVerticalOffset. Ta dołączona właściwość może być animowana.

Można również utworzyć metodę przedłużenia dla ItemsControl o nazwie AnimateScrollIntoView.

nazwać to jak ten

listBox.AnimateScrollIntoView(yourItem); 

ScrollViewerBehavior

public class ScrollViewerBehavior 
{ 
    public static DependencyProperty VerticalOffsetProperty = 
     DependencyProperty.RegisterAttached("VerticalOffset", 
              typeof(double), 
              typeof(ScrollViewerBehavior), 
              new UIPropertyMetadata(0.0, OnVerticalOffsetChanged)); 

    public static void SetVerticalOffset(FrameworkElement target, double value) 
    { 
     target.SetValue(VerticalOffsetProperty, value); 
    } 
    public static double GetVerticalOffset(FrameworkElement target) 
    { 
     return (double)target.GetValue(VerticalOffsetProperty); 
    } 
    private static void OnVerticalOffsetChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) 
    { 
     ScrollViewer scrollViewer = target as ScrollViewer; 
     if (scrollViewer != null) 
     { 
      scrollViewer.ScrollToVerticalOffset((double)e.NewValue); 
     } 
    } 
} 

ItemsControlExtensions

public static class ItemsControlExtensions 
{ 
    public static void AnimateScrollIntoView(this ItemsControl itemsControl, object item) 
    { 
     ScrollViewer scrollViewer = VisualTreeHelpers.GetVisualChild<ScrollViewer>(itemsControl); 

     UIElement container = itemsControl.ItemContainerGenerator.ContainerFromItem(item) as UIElement; 
     int index = itemsControl.ItemContainerGenerator.IndexFromContainer(container); 
     double toValue = scrollViewer.ScrollableHeight * ((double)index/itemsControl.Items.Count); 
     Point relativePoint = container.TranslatePoint(new Point(0.0, 0.0), Window.GetWindow(container)); 

     DoubleAnimation verticalAnimation = new DoubleAnimation(); 
     verticalAnimation.From = scrollViewer.VerticalOffset; 
     verticalAnimation.To = toValue; 
     verticalAnimation.DecelerationRatio = .2; 
     verticalAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(1000)); 
     Storyboard storyboard = new Storyboard(); 
     storyboard.Children.Add(verticalAnimation); 
     Storyboard.SetTarget(verticalAnimation, scrollViewer); 
     Storyboard.SetTargetProperty(verticalAnimation, new PropertyPath(ScrollViewerBehavior.VerticalOffsetProperty)); 
     storyboard.Begin(); 
    } 
} 

a ponieważ również trzeba się trzymać z ScrollViewer trzeba to

public static class VisualTreeHelpers 
{ 
    public static T GetVisualChild<T>(DependencyObject parent) where T : Visual 
    { 
     T child = default(T); 

     int numVisuals = VisualTreeHelper.GetChildrenCount(parent); 
     for (int i = 0; i < numVisuals; i++) 
     { 
      Visual v = (Visual)VisualTreeHelper.GetChild(parent, i); 
      child = v as T; 
      if (child == null) 
      { 
       child = GetVisualChild<T>(v); 
      } 
      if (child != null) 
      { 
       break; 
      } 
     } 
     return child; 
    } 
} 
+0

Jaka byłaby animacja. Czy warto przewijać w poziomie? – Cobold

+2

W kodzie może być błąd: 'scrollViewer.ScrollableHeight * ((double) index/itemsControl.Items.Count); ' powinno być ' scrollViewer.ScrollableHeight * ((podwójny) indeks/(itemsControl.Items.Count -1)); ' na przykład, jeśli lista zawiera 12 elementów i chcę, aby przejść do ostatniego (indeks 11), wynik musi stać ' scrollViewer.ScrollableHeight * 1 ' również, strzeż dzielenie przez zero:) – sim1

+0

@ sim1: Nie patrzyłem na to przez długi czas, więc jestem pewien, że masz rację. Dzięki za aktualizację :) –

0

Zapoznaj się z tym article, wyjaśnia, jak animowane przewijanie i dodawać gesty dotykowe. Pobierz źródło na dole strony i spójrz na rozwiązanie WpfScrollContent. Chciałbym rozszerzyć ListBox WPF i dodać animację przewijania do niego w ten sposób można ponownie użyć formantu.

+1

niedziałający link .... – patrickbadley

+0

napisali ponad 2 lata temu ... – evanb

+1

@evanb który jest dokładnie dlaczego odpowiedzi, które zawierają jedynie linki są zniechęceni. –