13

に のコレクションがVisualありListBoxます。その中の要素の を見つけて、 の をアニメーション化する必要がXPositionありHorizontalOffsetます。基本的に、アニメーション化されたメソッドを作成したいと考えています。ListBoxScrollViewerScrollIntoView

これにより、いくつかの問題が発生します。まず、スクロールビューアへの参照を取得するにはどうすればListBoxよいですか? 第二に、どのようにして相対XPositionまたはHozintalOfffset任意の要素を取得できListBoxますか?

ListBoxそれ自体の入力には応答しないため、Mouse関連するプロパティを使用できません。

4

2 に答える 2

33

ストーリーボードは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;
}

この関数は、パラメータータイプの最初のビジュアル子を返します。ScrollViewerFindVisualChild<ScrollViewer>(ListBox)を取得するために呼び出します。

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

お役に立てれば。

于 2009-03-20T11:45:45.383 に答える
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 }"/>
于 2015-02-09T10:00:24.833 に答える