Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Animating removed item in Listbox

I have some Listboxes in my app bound to ObservableCollections, and i would like to animate an item if it's being removed.

I already found a question about animating added items by using the FrameworkElement.Loaded event, but of course that doesn't work the same way with the Unloaded event.

Is there any way to do this in a way that can be used in a datatemplate?

EDIT: I've hooked up to the CollectionChanged event in my ItemsSource and tried to apply an animation manually. Currently it looks like this:

  ListBoxItem item = stack.ItemContainerGenerator.ContainerFromIndex(0) as ListBoxItem;
        item.LayoutTransform = new ScaleTransform(1, 1);

    DoubleAnimation scaleAnimation = new DoubleAnimation(); 
    scaleAnimation.From = 1; 
    scaleAnimation.To = 0; 
    scaleAnimation.Duration = new Duration(new TimeSpan(0, 0, 0, 0, 500));
    ScaleTransform transform = (ScaleTransform)item.LayoutTransform;
    transform.BeginAnimation(ScaleTransform.ScaleYProperty, scaleAnimation);

The problem is, it doesn't work at all. The item still just pops away. The item is still there when the method gets called, so shouldn't it be playing the animation before it disappears? Or am i doing it completely wrong?

like image 583
Botz3000 Avatar asked Apr 26 '09 17:04

Botz3000


3 Answers

I solved this by adding an IsRemoved property to the bound items. An event trigger in the ListViewItem container template is then bound which plays the removal animation when this bool changes to true. Concurrently, a Task is started with Task.Delay(n) matching the duration of the animation, and follows up with the actual removal from the collection. Note that this removal needs to be dispatched to the thread owning the list to avoid a cross thread exception.

void Remove(MyItem item, IList<MyItem> list)
{
    item.IsRemoved = true;

    Task.Factory.StartNew(() =>
        {
            Task.Delay(ANIMATION_LENGTH_MS);
            Dispatcher.Invoke(new Action(() => list.Remove(item)));
        });
}
like image 138
Jared G Avatar answered Nov 04 '22 08:11

Jared G


I don't have access to a code window at the moment so this is a little off the cuff, but could you extend the FrameworkElement with an Unloading event, then initiate that from CollectionChanged in an ObservableCollection. It means using a custom ObservableColleciton and custom FrameworkElement class but it could offer you what you need?

like image 1
ahin4114 Avatar answered Nov 04 '22 09:11

ahin4114


You can use Present.Commands Fluent API to change visual states during a command execution. I have posted an example of animating adding and removing items in a listbox using it here http://adammills.wordpress.com/2011/01/11/mvvm-animation-of-listbox-present-commands/

like image 1
Adam Mills Avatar answered Nov 04 '22 09:11

Adam Mills