2009-03-20 14 views
12

ListBox numaralı telefondan Visual s koleksiyonum var. İçindeki bir öğenin XPosition'unu bulmalı ve ardından ListBox'un ScrollViewer ürününün HorizontalOffset'u canlandırmam gerekir. Esasen animasyonlu bir ScrollIntoView yöntemini oluşturmak istiyorum.WPF - Animate ListBox.ScrollViewer.HorizontalOffset?

Bu bana birkaç sorun verir. İlk olarak, ListBox s scrollviewer'a nasıl başvuru yapabilirim? İkincisi, ListBox'daki rasgele bir öğenin göreli XPosition veya HozintalOfffset bağlantısını nasıl alabilirim?

ListBox üzerindeki herhangi bir girdiye yanıt veremiyorum, dolayısıyla Mouse ilgili özellikleri kullanamıyorum.

cevap

32

Animasyon için bir WPF hikaye panosu kullanabileceğinizi sanmıyorum çünkü storyboard'lar WPF bağımlılık özelliklerini canlandırıyor. Kaydırmak için ScrollViewer.ScrollToHorizontalOffset(double)'u aramanız gerekecektir.

SetHorizontalOffset öğesini OnDependencyPropertyChanged() işlevinde çağıran özel bir bağımlılık özelliği oluşturmayı deneyebilirsiniz. Sonra bu özelliği canlandırabilirsin.

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

kaydırma görüntüleyici ListBoxBindingContextChanged görsel çocukları aramak için VisualTreeHelper kullanabilirsiniz almak için. ScrollViewer'a bir referans kaydedin, çünkü daha sonra ihtiyacınız olacak. Bunu deneyin:

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

Bu işlev, parametre türünün ilk görsel alt öğesini döndürür. ScrollViewer'ı almak için FindVisualChild<ScrollViewer>(ListBox) numaralı telefonu arayın.

Son olarak, öğenin X konumunu almak için UIElement.TranslatePoint(Point, UIElement) kullanmayı deneyin. Öğede bu işlevi çağırın, nokta için 0,0 değerini geçirin ve ScrollViewer'da iletin.

Bu yardımcı olur umarım.

+0

Lordum, bu oldukça iş! Yardım için teşekkürler Josh, en azından doğru yönde bana işaret etti. – Stimul8d

+0

Bunu mu demek istediniz: ScrollToHorizontalOffset yerine SetHorizontalOffset? –

+0

Evet, haklısın. Teşekkürler! –

1

Yöntemimin iyi bir uygulama olup olmadığından emin değilim, ancak sınırlı bir süre için işe yaramış gibi görünüyordu. Bir hikaye tahtası kullanmak yerine, bunun yerine bir DispatcherTimer kullandım.

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

iplik Ayrıca görünümünde nesneyi bağlamak için hatırlamak UI öğesi

kontrolünü ele yapabiliyor yüzden bir DispatchTimer olduğundan emin ol!

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