Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
584 views
in Technique[技术] by (71.8m points)

animation - WPF - Animate ListBox.ScrollViewer.HorizontalOffset?

I have a collection of Visuals in a ListBox. I need to find the XPosition of an element inside it and then animate the HorizontalOffset of the ListBox's ScrollViewer. Essentially I want to created an animated ScrollIntoView method.

This gives me a couple of problems. Firstly, how can I get a reference to the ListBoxs scrollviewer? Secondly, how can i get the relative XPosition or HozintalOfffset of an arbitrary element in the ListBox?

I'm not reponding to any input on the ListBox itself so I can't use Mouse related properties.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I don't think you will be able to use a WPF storyboard for the animation because storyboards animate WPF dependency properties. You will need to call ScrollViewer.ScrollToHorizontalOffset(double) to scroll.

You could try creating a custom dependency property that calls SetHorizontalOffset in the OnDependencyPropertyChanged() function. Then you could animate this property.

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

To get the scroll viewer you can use the VisualTreeHelper to search the visual children of the ListBox. Save a reference to the ScrollViewer because you will need it later. Try this:

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

This function returns the first visual child of the parameter type. Call FindVisualChild<ScrollViewer>(ListBox) to get the ScrollViewer.

Finally, try using UIElement.TranslatePoint(Point, UIElement) to get the X position of the item. Call this function on the item, pass in 0,0 for the point, and pass in the ScrollViewer.

Hope this helps.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...