Анимация удаленного элемента в списке - PullRequest
5 голосов
/ 26 апреля 2009

У меня есть несколько списков в моем приложении, связанных с ObservableCollections, и я хотел бы анимировать элемент, если он удаляется.

Я уже нашел вопрос об анимации добавленных элементов с помощью события FrameworkElement.Loaded, но, конечно, это не работает аналогично событию Unloaded.

Есть ли способ сделать это так, чтобы его можно было использовать в табличке данных?

РЕДАКТИРОВАТЬ: я подключился к событию CollectionChanged в моем ItemsSource и попытался применить анимацию вручную. В настоящее время это выглядит так:

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

Проблема в том, что это не работает вообще. Элемент все еще просто исчезает. Элемент все еще там, когда метод вызывается, поэтому разве он не должен воспроизводить анимацию до того, как он исчезнет? Или я делаю это совершенно неправильно?

Ответы [ 4 ]

3 голосов
/ 12 июня 2013

Я решил это, добавив свойство IsRemoved к связанным элементам. Затем привязывается триггер события в шаблоне контейнера ListViewItem, который воспроизводит анимацию удаления, когда этот bool изменяется на true. Одновременно с этим Task запускается с Task.Delay (n), совпадающим с продолжительностью анимации, и выполняет фактическое удаление из коллекции. Обратите внимание, что это удаление необходимо отправить потоку, владеющему списком, чтобы избежать исключения между потоками.

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)));
        });
}
1 голос
/ 01 мая 2009

Оказалось, что даже если бы я вызывал событие перед его удалением, они все равно были бы удалены немедленно. Так как я использовал его в качестве наблюдаемого стека, я работал над этим, оставляя удаленный элемент в коллекции и удаляя его позже. как это:

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

Возможно, это не лучшее решение, но оно выполняет свою работу (по крайней мере, если я использую его только в качестве стека).

1 голос
/ 13 января 2011

Вы можете использовать Present.Commands Fluent API для изменения визуальных состояний во время выполнения команды. Я разместил пример анимации добавления и удаления элементов в списке, используя его здесь http://adammills.wordpress.com/2011/01/11/mvvm-animation-of-listbox-present-commands/

1 голос
/ 30 апреля 2009

В данный момент у меня нет доступа к окну кода, так что это немного не так, но вы могли бы расширить FrameworkElement событием Unloading, а затем инициировать его из CollectionChanged в ObservableCollection. Это означает использование пользовательского ObservableColleciton и пользовательского класса FrameworkElement, но он может предложить вам то, что вам нужно?

...