2011-05-06 39 views
7

ListBox (ListView) tabanlı bir kullanıcı denetimi oluşturmak için bu tür bir animasyon ile: liste kutusundaki öğeler bir kerede yüklenmez, adım adım yükleme yapmaları gerekir (öğe-by-item, ilk önce ikinci, sonra üçüncü, vs.) aralarında zaman aşımı ile.ListBox öğesi, yük animasyonu

Bunu nasıl yapabilirim?

cevap

10

Bunun için bir Blend SDK davranışı kullanabilirsiniz.

<ListBox ItemsSource="{Binding Collection, Source={StaticResource SampleData}}"> 
    <i:Interaction.Behaviors> 
     <b:FadeAnimateItemsBehavior Tick="0:0:0.05"> 
      <b:FadeAnimateItemsBehavior.Animation> 
       <DoubleAnimation From="0" To="1" Duration="0:0:0.3"/> 
      </b:FadeAnimateItemsBehavior.Animation> 
     </b:FadeAnimateItemsBehavior> 
    </i:Interaction.Behaviors> 
</ListBox> 
class FadeAnimateItemsBehavior : Behavior<ListBox> 
{ 
    public DoubleAnimation Animation { get; set; } 
    public TimeSpan Tick { get; set; } 

    protected override void OnAttached() 
    { 
     base.OnAttached(); 
     AssociatedObject.Loaded += new System.Windows.RoutedEventHandler(AssociatedObject_Loaded); 
    } 

    void AssociatedObject_Loaded(object sender, System.Windows.RoutedEventArgs e) 
    { 
     IEnumerable<ListBoxItem> items; 
     if (AssociatedObject.ItemsSource == null) 
     { 
      items = AssociatedObject.Items.Cast<ListBoxItem>(); 
     } 
     else 
     { 
      var itemsSource = AssociatedObject.ItemsSource; 
      if (itemsSource is INotifyCollectionChanged) 
      { 
       var collection = itemsSource as INotifyCollectionChanged; 
       collection.CollectionChanged += (s, cce) => 
        { 
         if (cce.Action == NotifyCollectionChangedAction.Add) 
         { 
          var itemContainer = AssociatedObject.ItemContainerGenerator.ContainerFromItem(cce.NewItems[0]) as ListBoxItem; 
          itemContainer.BeginAnimation(ListBoxItem.OpacityProperty, Animation); 
         } 
        }; 

      } 
      ListBoxItem[] itemsSub = new ListBoxItem[AssociatedObject.Items.Count]; 
      for (int i = 0; i < itemsSub.Length; i++) 
      { 
       itemsSub[i] = AssociatedObject.ItemContainerGenerator.ContainerFromIndex(i) as ListBoxItem; 
      } 
      items = itemsSub; 
     } 
     foreach (var item in items) 
     { 
      item.Opacity = 0; 
     } 
     var enumerator = items.GetEnumerator(); 
     if (enumerator.MoveNext()) 
     { 
      DispatcherTimer timer = new DispatcherTimer() { Interval = Tick }; 
      timer.Tick += (s, timerE) => 
      { 
       var item = enumerator.Current; 
       item.BeginAnimation(ListBoxItem.OpacityProperty, Animation); 
       if (!enumerator.MoveNext()) 
       { 
        timer.Stop(); 
       } 
      }; 
      timer.Start(); 
     } 
    } 
} 

Tick ürün solmaya başladı zaman arasındaki süreyi belirtir Animation fade Opaklık uygulanan animasyon in, Xaml'da çok costomize edilebilir (örn. fonksiyonları ve solma süresini kısaltmak) olarak ayarlanabilir.

Düzenleme:. Dikkatli böyle

(kullanın kod parçacıkları (ItemsSource kullanılan ve INotifyCollectionChanged uygulayan ise sadece çalışır) hiç değilse, bu kod gösteri amaçlı ağırlıklı yeni öğe solma olan Katma ve Buna nasıl yaklaşılabileceğine dair genel bir fikir vermek mümkündür. Bu, muhtemelen, Blend 4'ün yerel FluidMoveBehaviors kullanılarak yapılabilir.)

+0

Bu tür nitelikli yanıt için teşekkürler! Nihayet, Opaklık özelliği olmayan öğeleri, ancak Görünürlük özelliğini kullanarak nasıl animasyon uygularım? Çok denedim ama yapamam. – JaneKate

+0

Bir ['ObjectAnimationUsingKeyFrames'] kullanarak görünürlüğü canlandırabilirsiniz (http://msdn.microsoft.com/en-us/library/system.windows.media.animation.objectanimationusingkeyframes%28v=vs.95%29.aspx), [bu cevap] 'da (http://stackoverflow.com/questions/5587374/animating-wpf-datagrid-row-details/5588022#5588022) bir örnek görebilirsiniz. –

+0

Teşekkürler! Böyle bir animasyon (ya da davranış) özel bir isim (akordeon? - en iyi olabilir!) Olmadığı için cevap bulmaya çalıştı. – JaneKate