WP7 - Animating add/remove item in a ListBox

2019-02-17 04:25发布

问题:

I know you can achieve this in Silverlight 4 by playing with the ListBoxItem style's LayoutStates, i.e. BeforeUnloaded, BeforeLoaded and AfterLoaded.

It doesn't seem to be working at all in WP7 although these states exist in the default style.

I am currently using version 7.1.

Is there any way I can get this working?

Thanks, Xin

回答1:

for this I used Artefact Animator, it's for Silverlight but works perfectly for WP7 also. The code shows only the addition. Whole code from the project's sample page.

MainPage.xaml

<UserControl.Resources>

    <!-- ADDS SMOOTH SCROLL -->
    <ItemsPanelTemplate x:Key="ItemsPanelTemplate">
        <StackPanel/>
    </ItemsPanelTemplate>

</UserControl.Resources>
<Grid>
    <ListBox x:Name="lb" Height="247" Width="100" ItemsPanel="{StaticResource ItemsPanelTemplate}" />
    <Button x:Name="addBtn" Content="Add" Height="72" HorizontalAlignment="Left" Margin="159,145,0,0"  VerticalAlignment="Top" Width="160" />
</Grid>

MainPage.xaml.cs

public partial class MainPage : PhoneApplicationPage
{
    private static ScrollViewer _scrollViewer;
    // Constructor
    public MainPage()
    {
        InitializeComponent();
        Loaded += MainPage_Loaded;
    }

    void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        // INIT
        lb.Items.Clear();
        lb.UpdateLayout();

        // SCROLL INTERACTION
        _scrollViewer = FindVisualChild<ScrollViewer>(lb);
        var bar = FindVisualChild<ScrollBar>(_scrollViewer);
        if (bar != null)
            bar.ValueChanged += (s, args) => SetValue(ListBoxScrollOffsetProperty, args.NewValue);

        // INPUT
        addBtn.Click += (s, args) => AddItem();
    }

    private void AddItem()
    {
        // Create New ListBoxItem
        var lbi = new ListBoxItem
        {
            Content = "Item " + lb.Items.Count,
            RenderTransform = new CompositeTransform
            {
                TranslateX = -lb.Width
            },
        };

        // Add ListBoxItem
        lb.Items.Add(lbi);
        lb.UpdateLayout();

        // Animate In Item
        ArtefactAnimator.AddEase(lbi.RenderTransform, CompositeTransform.TranslateXProperty, 0, 1, AnimationTransitions.CubicEaseOut, 0);
        ArtefactAnimator.AddEase(this, ListBoxScrollOffsetProperty, _scrollViewer.ScrollableHeight, .8, AnimationTransitions.CubicEaseOut, 0);
    }


    // LISTBOX SCROLL OFFSET
    public static readonly DependencyProperty ListBoxScrollOffsetProperty =
    DependencyProperty.Register("ListBoxScrollOffset", typeof(double), typeof(MainPage), new PropertyMetadata(0.0, OnListBoxScrollOffsetChanged));

    private static void OnListBoxScrollOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        _scrollViewer.ScrollToVerticalOffset((double)e.NewValue);
    }

    public double ListBoxScrollOffset
    {
        get
        {
            return (double)GetValue(ListBoxScrollOffsetProperty);
        }
        set
        {
            SetValue(ListBoxScrollOffsetProperty, value);
        }
    }

    // VISUAL HELPER
    public static childItem FindVisualChild<childItem>(DependencyObject obj) where childItem : DependencyObject
    {
        for (var i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
        {
            var child = VisualTreeHelper.GetChild(obj, i);
            if (child != null && child is childItem)
            {
                return (childItem)child;
            }
            else
            {
                var childOfChild = FindVisualChild<childItem>(child);
                if (childOfChild != null)
                {
                    return childOfChild;
                }
            }
        }
        return null;
    }
}