ListBox item load animation

时间秒杀一切 提交于 2019-11-29 19:49:35

问题


I want to create user control based on ListBox (ListView) with such animation: the items in listbox do not loads all at once, they have to load step-by-step (item-by-item, first then second, then third, etc.) with some timeout between them.

How can I do that?


回答1:


You could use a Blend SDK behavior for this:

<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 specifies the time between when items are started to fade in. Animation is the animation applied to the Opacity for the fade in, it can be set in Xaml to be very costomizable (e.g. easing functions and fade time).

Edit: Added new item fade in (only works if ItemsSource is used and implements INotifyCollectionChanged)

(Use code snippets like this with caution, if at all. This code is mainly for demonstration purposes and giving a general idea of how this can be approached. This could probably also be done using Blend 4's native FluidMoveBehaviors if availabe.)



来源:https://stackoverflow.com/questions/5910215/listbox-item-load-animation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!