WPF-Animate ListBox.ScrollViewer.HorizontalOffset?

j'ai une collection de Visual s dans un ListBox . Je dois trouver le XPosition d'un élément à l'intérieur de lui et puis animer le HorizontalOffset du ListBox 's ScrollViewer . Essentiellement je veux créer une animation ScrollIntoView méthode.

cela me pose quelques problèmes. Tout d'abord, comment puis-je obtenir une référence au ListBox s scrollviewer? Deuxièmement, Comment puis-je obtenir le relatif XPosition ou HozintalOfffset d'un élément arbitraire dans le ListBox ?

Je ne réponds à aucune entrée sur le ListBox lui-même donc je ne peux pas utiliser Mouse propriétés connexes.

12
demandé sur WendiKidd 2009-03-20 14:15:09

2 réponses

Je ne pense pas que vous pourrez utiliser un storyboard WPF pour l'animation car les storyboards animent les propriétés de dépendance WPF. Vous devez appeler ScrollViewer.ScrollToHorizontalOffset(double) pour faire défiler.

vous pouvez essayer de créer une propriété de dépendance personnalisée qui appelle SetHorizontalOffset dans la fonction OnDependencyPropertyChanged (). Alors vous pourriez animer cette propriété.

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

pour obtenir le scroll viewer vous pouvez utiliser le VisualTreeHelper pour rechercher visual enfants de la zone de liste. Enregistrez une référence au ScrollViewer car vous en aurez besoin plus tard. Essayez ceci:

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

cette fonction renvoie le premier enfant visuel du type de paramètre. Appelez FindVisualChild<ScrollViewer>(ListBox) pour obtenir le ScrollViewer.

enfin, essayez d'utiliser UIElement.TranslatePoint(Point, UIElement) pour obtenir la position X de l'élément. Appeler cette fonction sur l'élément, passer dans 0,0 pour le point, et passer dans le ScrollViewer.

Espérons que cette aide.

32
répondu Josh G 2015-03-11 12:34:46

Je ne suis pas sûr si ma méthode est une bonne pratique, mais pour le temps limité que j'avais, il semblait fonctionner bien. Au lieu d'utiliser un story board, j'ai utilisé 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();
               }
           };
       });

assurez-vous que c'est un répartiteur pour que le thread puisse prendre le contrôle de L'élément UI

n'oubliez pas non plus de vous attacher à votre objet dans votre vue!

<Button CommandParameter="{Binding ElementName=MyScrollViewer }"
        Command="{Binding ScrollLeftButtonCommand }"/>
1
répondu RagedMilkMan 2015-02-09 10:00:24