2009-03-20 6 views
12

私は、にVisualのコレクションを持っています。私はそれの中に要素のXPositionを見つけて、ListBoxScrollViewerHorizontalOffsetをアニメーション化する必要があります。基本的には、アニメーション化されたScrollIntoViewメソッドを作成したいと考えています。WPF - Animate ListBox.ScrollViewer.Horizo​​ntalOffset?

これは私にいくつかの問題をもたらします。まず、スクロールビューアのListBoxへの参照を取得するにはどうすればよいですか?次に、ListBoxの任意の要素の相対番号XPositionまたはHozintalOfffsetを取得するにはどうすればよいですか。

私はListBoxの入力には反応しませんので、Mouseの関連プロパティは使用できません。

答えて

32

ストーリーボードがWPF依存プロパティをアニメーション化するため、アニメーションにWPFストーリーボードを使用することはできません。スクロールするにはScrollViewer.ScrollToHorizontalOffset(double)に電話する必要があります。

OnDependencyPropertyChanged()関数でSetHorizo​​ntalOffsetを呼び出すカスタム依存関係プロパティを作成してみることもできます。その後、このプロパティをアニメートできます。

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

スクロールビューアを取得するには、VisualTreeHelperを使用してListBoxのビジュアルな子を検索できます。後で必要となるため、ScrollViewerへの参照を保存します。これを試してください:

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

この関数は、パラメータタイプの最初の視覚的な子を返します。 FindVisualChild<ScrollViewer>(ListBox)に電話してScrollViewerを入手してください。

最後に、UIElement.TranslatePoint(Point, UIElement)を使用してアイテムのX位置を取得してみてください。アイテムに対してこの関数を呼び出し、ポイントの0,0を渡してScrollViewerを渡します。

これが役に立ちます。

+0

私の主人は、かなり仕事です!助けをくれてありがとうジョシュ、それは正しい方向に少なくとも私を指摘している。 – Stimul8d

+0

SetHorizo​​ntalOffsetではなくScrollToHorizo​​ntalOffsetを意味しますか? –

+0

はい、そうです。ありがとう! –

1

私の方法が良い練習であるかどうかはわかりませんが、限られた時間の間、私はそれが問題なく動作していたようです。ストーリーボードを使用するのではなく、代わりに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(); 
       } 
      }; 
     }); 

スレッドはまた、あなたのビューでオブジェクトにバインドするために覚えているUI要素

の制御を取ることができているので、それはDispatchTimerだことを確認してください!

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