2011-05-06 39 views
7

我想用這樣的動畫創建基於ListBox(ListView)的用戶控件:listbox中的項目不會一次加載全部,它們必須逐步加載(逐個項目,先是然後第二次,然後是第三次等),在它們之間有一些超時。ListBox項加載動畫

我該怎麼做?

回答

10

您可以使用此混合SDK行爲:

<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指定當項目開始淡出之間的時間Animation是適用於不透明度的漸變動畫在Xaml中,它可以設置爲非常可定製的(例如,緩動功能和淡入淡出時間)。

編輯:添加新項褪色

使用代碼片段這樣的謹慎(僅在使用的ItemsSource和實現INotifyCollectionChanged作品),如果在所有這些代碼主要用於演示目的,大概也可以用Blend 4的本地FluidMoveBehaviors來完成,如果可以的話。

+0

感謝這樣合格的答案! 最後,我怎樣才能讓沒有不透明屬性的物品動畫,但是具有可見性屬性。我嘗試了很多,但不能這樣做。 – JaneKate 2011-05-16 12:43:08

+0

您可以使用['ObjectAnimationUsingKeyFrames'](http://msdn.microsoft.com/en-us/library/system.windows.media.animation.objectanimationusingkeyframes%28v=vs.95%29.aspx)動畫可見性,在[這個答案](http://stackoverflow.com/questions/5587374/animating-wpf-datagrid-row-details/5588022#5588022)你可以看到一個例子。 – 2011-05-16 12:47:29

+0

謝謝!它試圖找到答案,因爲這樣的動畫(或行爲)沒有特殊的名字(手風琴? - 可能是最好的!)。 – JaneKate 2011-05-16 12:51:38