在列表框中动画删除的项目

我的应用程序中有一些Listboxes绑定到ObservableCollections,我想动画一个项目,如果它被删除。

我已经发现了一个关于使用FrameworkElement.Loaded事件动画添加项目的问题,但当然这与Unloaded事件的工作方式不同。

有没有办法以可以在datatemplate中使用的方式执行此操作?

编辑:我已经连接到我的ItemsSource中的CollectionChanged事件,并尝试手动应用动画。 目前它看起来像这样:

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); 

问题是,它根本不起作用。 该项目仍然只是弹出。 当方法被调用时,该项目仍然存在,所以它不应该在它消失之前播放动画吗? 或者我完全错了吗?

我通过向绑定项添加IsRemoved属性来解决这个问题。 然后绑定ListViewItem容器模板中的事件触发器,当此bool更改为true时播放删除动画。 同时,使用与动画持续时间匹配的Task.Delay(n)启动任务,并从集合中实际删除。 请注意,需要将此删除分派给拥有列表的线程,以避免跨线程exception。

 void Remove(MyItem item, IList list) { item.IsRemoved = true; Task.Factory.StartNew(() => { Task.Delay(ANIMATION_LENGTH_MS); Dispatcher.Invoke(new Action(() => list.Remove(item))); }); } 

我目前无法访问代码窗口,所以这有点偏离了袖口,但是你可以使用Unloading事件扩展FrameworkElement,然后在ObservableCollection中从CollectionChanged启动它。 这意味着使用自定义ObservableColleciton和自定义FrameworkElement类,但它可以为您提供所需的内容?

您可以使用Present.Commands Fluent API在命令执行期间更改可视状态。 我已经发布了一个动画示例,在这里使用它来添加和删除列表框中的项目http://adammills.wordpress.com/2011/01/11/mvvm-animation-of-listbox-present-commands/

事实certificate,即使我在移除它们之前提出了一个事件,它们也会立即被移除。 因此,当我使用它作为可观察的堆栈时,我通过将删除的元素留在集合中并稍后将其删除来解决这个问题。 像这样:

 public class ObservableStack : ObservableCollection { private T collapsed; public event EventHandler BeforePop; public T Peek() { if (collapsed != null) { Remove(collapsed); collapsed = default(T); } return this.FirstOrDefault(); } public T Pop() { if (collapsed != null) { Remove(collapsed); } T result = (collapsed = this.FirstOrDefault()); if (BeforePop != null && result != null) BeforePop(this, new EventArgs()); return result; } public void Push(T item) { if (collapsed != null) { Remove(collapsed); collapsed = default(T); } Insert(0, item); } } 

可能不是最好的解决方案,但它完成了工作(至少如果我只将它用作堆栈)。