首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

WPF 實現 QQ 風格分組面板(進階版):Behavior 動畫實現展開收合效果

     編輯:關於.NET

上文介紹自定義 Panel 實現 QQ 分組面板,但有兩大缺點:失去虛擬化效能、難以添加動畫。本文使用 Blend 3 Behavior 重新實現,輕鬆添加動畫效果。

Behavior 核心原理

動態計算 ListBox 中 Item 高度。前提條件:

  1. 不為 Item 指定不相同高度
  2. 為每個 Item 指定預設收合高度

優於前人方案:充分利用 WPF 特性、無冗餘邏輯(如 Expander.IsExpanded)、完整動畫支援。

Behavior 實作步驟

  1. 建立針對 ListBox 的自定義 Behavior
  2. 在 SelectionChanged 事件中設定每個 Item 高度
  3. 使用 Storyboard + DoubleAnimation 實現平滑動畫

自定義屬性

  • DefaultHeight:收合狀態高度
  • AnimationDuration:動畫持續時間(毫秒)

核心邏輯代碼

private void OnAssociatedObjectSelectionChanged(object sender, SelectionChangedEventArgs e) {
    double selectedItemFinalHeight = AssociatedObject.ActualHeight;
    Storyboard storyBoard = new Storyboard();
    
    for (int i = 0; i < AssociatedObject.Items.Count; i++) {
        ListBoxItem item = AssociatedObject.ItemContainerGenerator.ContainerFromIndex(i) as ListBoxItem;
        if (!item.IsSelected) {
            selectedItemFinalHeight -= DefaultHeight;
            DoubleAnimation heightAnimation = new DoubleAnimation {
                To = DefaultHeight,
                Duration = new Duration(TimeSpan.FromMilliseconds(AnimationDuration))
            };
            Storyboard.SetTarget(heightAnimation, item);
            Storyboard.SetTargetProperty(heightAnimation, new PropertyPath(FrameworkElement.HeightProperty));
            storyBoard.Children.Add(heightAnimation);
        }
    }
    
    // ListBox 內邊距補償
    selectedItemFinalHeight -= 4;
    if (AssociatedObject.SelectedIndex >= 0) {
        ListBoxItem selectedItem = AssociatedObject.ItemContainerGenerator.ContainerFromIndex(AssociatedObject.SelectedIndex) as ListBoxItem;
        DoubleAnimation fillHeightAnimation = new DoubleAnimation {
            To = selectedItemFinalHeight,
            Duration = new Duration(TimeSpan.FromMilliseconds(AnimationDuration))
        };
        Storyboard.SetTarget(fillHeightAnimation, selectedItem);
        Storyboard.SetTargetProperty(fillHeightAnimation, new PropertyPath(FrameworkElement.HeightProperty));
        storyBoard.Children.Add(fillHeightAnimation);
    }
    storyBoard.Begin(AssociatedObject);
}

效果與優勢

  • 視覺效果同前文,但具備平滑展開/收合動畫
  • 保留 ListBox 原生虛擬化潛力(未破壞 Item 容器生成機制)
  • Behavior 可複用,純 XAML 掛載,無侵入性
  • 代碼包含上一版 Panel 實現,可對比學習

動畫效果需親自運行體驗。本文配套完整原始碼可下載。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved