簡體   English   中英

對列表框中的已刪除項目進行動畫處理

[英]Animating removed item in Listbox

我的應用程序中有一些與ObservableCollections綁定的列表框,如果要刪除某個項目,我想為其設置動畫。

我已經找到了一個有關使用FrameworkElement.Loaded事件為添加的項目設置動畫的問題,但是,當然,這與Unloaded事件的工作方式不同。

有什么方法可以在數據模板中使用嗎?

編輯:我已經連接到我ItemsItemSource中的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容器模板中的事件觸發器,當該布爾值更改為true時,該事件觸發器將播放移除動畫。 同時,以Task.Delay(n)匹配動畫的持續時間開始Task,然后從集合中實際移除。 請注意,此刪除操作需要分派給擁有該列表的線程,以避免跨線程異常。

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

您可以使用Present.Commands Fluent API在命令執行期間更改視覺狀態。 我在此處發布了一個使用列表在動畫中添加和刪除項目的動畫示例,網址為http://adammills.wordpress.com/2011/01/11/mvvm-animation-of-listbox-present-commands/

我目前無法訪問代碼窗口,因此這有點麻煩,但是您可以通過Unloading事件擴展FrameworkElement,然后從ObservableCollection中的CollectionChanged發起該事件。 這意味着使用自定義的ObservableColleciton和自定義的FrameworkElement類,但它可以為您提供所需的內容?

事實證明,即使我在刪除事件之前發起了一個活動,它們也將立即被刪除。 因此,當我將其用作可觀察的堆棧時,我通過將已刪除的元素保留在集合中並稍后將其刪除來解決此問題。 像這樣:

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

可能不是最好的解決方案,但是它可以完成工作(至少如果我僅將其用作堆棧)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM