Animating removed item in Listbox

半腔热情 提交于 2019-12-02 21:23:48

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

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?

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/

It turned out that even if i was raising an event before removing them, they would get removed instantly anyway. So as i was using it as an observable stack, i worked around this by leaving the removed element in the collection and removing it later. like this:

public class ObservableStack<T> : ObservableCollection<T> 
{
    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);
    }
}

Might not be the best solution, but it does the job (at least if i only use it as a stack).

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