原文章
通过对数据进行分组、排序和过滤,以不同的方式查看DataGrid中的数据通常很有用。要对DataGrid中的数据进行分组、排序和筛选,需要将其绑定到支持这些功能的CollectionView。然后,可以在CollectionView中处理数据,而不影响底层源数据。集合视图中的更改反映在DataGrid用户界面(UI)中。
CollectionView类为实现IEnumerable接口的数据源提供分组和排序功能。CollectionViewSource类允许您从XAML设置CollectionView的属性。
在本例中,任务对象的集合绑定到CollectionViewSource。CollectionViewSource用作DataGrid的ItemsSource。分组、排序和筛选在CollectionViewSource上执行,并显示在DataGrid UI中。
将CollectionViewSource用作ItemsSource
要对DataGrid控件中的数据进行分组、排序和筛选,需要将DataGrid绑定到支持这些功能的CollectionView。在本例中,DataGrid绑定到CollectionViewSource,后者为Task对象列表(List)提供这些函数。
将DataGrid绑定到CollectionViewSource的步骤
- 创建一个实现IEnumerable接口的数据集合。
如果使用List创建集合,则应该创建一个从List继承的新类,而不是实例化List的实例。这使您能够将数据绑定到XAML中的集合。
// Requires using System.Collections.ObjectModel;
public class Tasks : ObservableCollection<Task>
{
// Creating the Tasks collection in this way enables data binding from XAML.
}
- 在XAML中,创建collection类的实例并设置x:Key指令。
- 在XAML中,创建CollectionViewSource类的实例,设置x:Key指令,并将collection类的实例设置为源。
<Window.Resources>
<local:Tasks x:Key="tasks" />
<CollectionViewSource x:Key="cvsTasks" Source="{StaticResource tasks}"
Filter="CollectionViewSource_Filter">
</CollectionViewSource>
</Window.Resources>
- 创建DataGrid类的实例,并将ItemsSource属性设置为CollectionViewSource。
<DataGrid x:Name="dataGrid1"
ItemsSource="{Binding Source={StaticResource cvsTasks}}"
CanUserAddRows="False">
- 要从代码中访问CollectionViewSource,请使用GetDefaultView方法获取对CollectionViewSource的引用。
ICollectionView cvTasks = CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource);
在DataGrid中对项目进行分组
要指定项目在DataGrid中的分组方式,可以使用PropertyGroupDescription类型对源代码视图中的项目进行分组。
使用XAML对DataGrid中的项进行分组
- 创建一个PropertyGroupDescription,指定分组依据的属性。可以在XAML或代码中指定属性。
a. 在XAML中,将PropertyName设置为要分组的属性的名称。
b. 在代码中,将要分组的属性的名称传递给构造函数。 - 将PropertyGroupDescription添加到CollectionViewSource.GroupDescriptions集合。
- 将PropertyGroupDescription的其他实例添加到GroupDescriptions集合,以添加更多级别的分组。
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="ProjectName"/>
<PropertyGroupDescription PropertyName="Complete"/>
</CollectionViewSource.GroupDescriptions>
ICollectionView cvTasks = CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource);
if (cvTasks != null && cvTasks.CanGroup == true)
{
cvTasks.GroupDescriptions.Clear();
cvTasks.GroupDescriptions.Add(new PropertyGroupDescription("ProjectName"));
cvTasks.GroupDescriptions.Add(new PropertyGroupDescription("Complete"));
}
- 要删除组,请从GroupDescriptions集合中删除PropertyGroupDescription。
- 要删除所有组,请调用GroupDescriptions集合的Clear方法。
ICollectionView cvTasks = CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource);
if (cvTasks != null)
{
cvTasks.GroupDescriptions.Clear();
}
在DataGrid中对项目进行分组时,可以定义一个GroupStyle来指定每个组的外观。您可以通过将GroupStyle添加到DataGrid的GroupStyle集合来应用它。如果有多个级别的分组,可以对每个级别的分组应用不同的样式。样式将按其定义的顺序应用。例如,如果定义两种样式,第一种样式将应用于顶级行组。第二种样式将应用于第二级及更低级别的所有行组。GroupStyle的DataContext是该组表示的CollectionViewGroup。
更改行组标题外观的步骤
- 创建定义行组外观的GroupStyle。
- 将GroupStyle放入<DataGrid.GroupStyle>标签。
<DataGrid.GroupStyle>
<!-- Style for groups at top level. -->
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Margin" Value="0,0,0,5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="True" Background="#FF112255" BorderBrush="#FF002255" Foreground="#FFEEEEEE" BorderThickness="1,1,1,5">
<Expander.Header>
<DockPanel>
<TextBlock FontWeight="Bold" Text="{Binding Path=Name}" Margin="5,0,0,0" Width="100"/>
<TextBlock FontWeight="Bold" Text="{Binding Path=ItemCount}"/>
</DockPanel>
</Expander.Header>
<Expander.Content>
<ItemsPresenter />
</Expander.Content>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
<!-- Style for groups under the top level. -->
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<DockPanel Background="LightBlue">
<TextBlock Text="{Binding Path=Name, Converter={StaticResource completeConverter}}" Foreground="Blue" Margin="30,0,0,0" Width="100"/>
<TextBlock Text="{Binding Path=ItemCount}" Foreground="Blue"/>
</DockPanel>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</DataGrid.GroupStyle>
在DataGrid中对项目进行排序
要指定项目在DataGrid中的排序方式,可以使用SortDescription类型对源代码视图中的项目进行排序。
对DataGrid中的项目进行排序
- 创建一个SortDescription,指定排序依据的属性。可以在XAML或代码中指定属性。
a. 在XAML中,将PropertyName设置为要排序的属性的名称。
b. 在代码中,将要排序的属性的名称和ListSortDirection传递给构造函数。 - 将SortDescription添加到CollectionViewSource。SortDescriptions系列。
- 将SortDescription的其他实例添加到SortDescriptions集合中,以按其他属性排序。
<CollectionViewSource.SortDescriptions>
<!-- Requires 'xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"' declaration. -->
<scm:SortDescription PropertyName="ProjectName"/>
<scm:SortDescription PropertyName="Complete" />
<scm:SortDescription PropertyName="DueDate" />
</CollectionViewSource.SortDescriptions>
// Requires using System.ComponentModel;
ICollectionView cvTasks = CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource);
if (cvTasks != null && cvTasks.CanSort == true)
{
cvTasks.SortDescriptions.Clear();
cvTasks.SortDescriptions.Add(new SortDescription("ProjectName", ListSortDirection.Ascending));
cvTasks.SortDescriptions.Add(new SortDescription("Complete", ListSortDirection.Ascending));
cvTasks.SortDescriptions.Add(new SortDescription("DueDate", ListSortDirection.Ascending));
}
筛选DataGrid中的项
要使用CollectionViewSource过滤DataGrid中的项,请在CollectionViewSource的处理程序中提供筛选逻辑,筛选事件。
筛选DataGrid中的项
- 为CollectionViewSource添加处理程序,筛选事件。
- 在筛选器事件处理程序中,定义过滤逻辑。
每次刷新视图时都会应用过滤器。
<CollectionViewSource x:Key="cvsTasks" Source="{StaticResource tasks}"
Filter="CollectionViewSource_Filter">
private void CollectionViewSource_Filter(object sender, FilterEventArgs e)
{
Task t = e.Item as Task;
if (t != null)
// If filter is turned on, filter completed items.
{
if (this.cbCompleteFilter.IsChecked == true && t.Complete == true)
e.Accepted = false;
else
e.Accepted = true;
}
}
或者,您可以通过创建提供过滤逻辑的方法并设置CollectionView.Filter 属性以应用筛选器来过滤DataGrid中的项 。要查看此方法的示例,请参见在视图中过滤数据。