在 WPF 中,當我們將控制項繫結到集合對象時,框架會自動提供一個 CollectionViewSource 視圖。這個視圖關聯著源集合,並能自動將排序、分組、過濾等操作反映到目標 UI 上。本文將詳細介紹如何透過程式碼或 XAML 實現這些功能,並示範資料導航的常用技巧。
透過 CollectionViewSource.SortDescriptions 屬性加入一個或多個 SortDescription,即可實現單欄或多欄排序。修改排序條件會即時更新介面顯示。
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
var personals = this.FindResource("personals");
var view = CollectionViewSource.GetDefaultView(personals);
view.SortDescriptions.Add(new SortDescription("Age", ListSortDirection.Ascending));
}
}
在資源中定義 CollectionViewSource,並設定 SortDescriptions,注意需引入 xmlns:model="clr-namespace:System.ComponentModel;assembly=WindowsBase" 命名空間。
<Window.Resources>
<my:PersonalList x:Key="personals">
<my:Personal Name="Tom" Age="15" Sex="Male" />
<my:Personal Name="Mary" Age="11" Sex="Female" />
<my:Personal Name="Jack" Age="12" Sex="Male" />
</my:PersonalList>
<CollectionViewSource x:Key="cvs" Source="{StaticResource personals}">
<CollectionViewSource.SortDescriptions>
<model:SortDescription PropertyName="Age" />
<model:SortDescription PropertyName="Sex" Direction="Descending" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
</Window.Resources>
<Grid>
<StackPanel DataContext="{StaticResource cvs}">
<ListBox ItemsSource="{Binding}" ... />
</StackPanel>
</Grid>
關鍵點:目標控制項的 DataContext 需綁定到視圖 (cvs) 而非原始資料源 (personals)。
使用 CollectionViewSource.GroupDescriptions 加入 PropertyGroupDescription 即可對資料分組。若要在 UI 顯示分組標頭,必須為 ListBox 設定 GroupStyle(可直接使用 GroupStyle.Default)。
var view = CollectionViewSource.GetDefaultView(personals);
view.GroupDescriptions.Add(new PropertyGroupDescription("Sex"));
需引入 xmlns:data="clr-namespace:System.Windows.Data;assembly=PresentationFramework"。
<CollectionViewSource x:Key="cvs" Source="{StaticResource personals}">
<CollectionViewSource.GroupDescriptions>
<data:PropertyGroupDescription PropertyName="Sex" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
透過 CollectionViewSource.Filter 委派,可自訂過濾邏輯。例如只顯示男性:
var view = CollectionViewSource.GetDefaultView(personals);
view.Filter = o => (o as Personal).Sex != Sex.Female;
集合視圖內建當前項目指標,配合 IsSynchronizedWithCurrentItem="True" 可實現主從介面聯動。常用導航方法:
MoveCurrentToFirst()MoveCurrentToPrevious()MoveCurrentToNext()MoveCurrentToLast()MoveCurrentToPosition(index)繫結語法:{Binding /} 表示當前項目,{Binding /Name} 表示當前項目的 Name 屬性。





