在WPF中预先对DataGrid进行排序

26
我在 WPF 应用程序中有一个 DataGrid,其中包括一个名称列。如果用户切换到特定视图,我希望数据按名称预排序(并且我希望在名称标题中出现排序箭头,就像用户单击该标题一样)。但是,我找不到使此发生的期望属性。我正在寻找类似于 SortColumn、SortColumnIndex、SortDirection 等属性。
是否可以在标记中指定默认排序列和方向(XAML),或者 WPF Toolkit 中的 DataGrid 不支持此功能?

由于WPF没有内置DataGrid,我们可以假设您是指随WPF Toolkit(http://www.codeplex.com/wpf)提供的DataGrid吗? - Drew Marsh
是的,我放了wpftoolkit标签,但我想我没有在我的问题中提到它。我会补充说明的。 - devuxer
5个回答

48

假设你在谈论WPF Toolkit DataGrid控件,那么你只需要将CanUserSortColumns属性设置为true,然后在DataGrid中的每个DataGridColumn上设置SortMemberPath属性

至于最初对集合进行排序,您必须使用CollectionViewSource并对其进行排序,然后将其分配为DataGrid的ItemsSource。如果您正在使用XAML进行此操作,则非常简单:

<Window.Resources>
    <CollectionViewSource x:Key="MyItemsViewSource" Source="{Binding MyItems}">
        <CollectionViewSource.SortDescriptions>
           <scm:SortDescription PropertyName="MyPropertyName"/>
        </CollectionViewSource.SortDescriptions>
    </CollectionViewSource>
</Window.Resources>

<DataGrid ItemsSource="{StaticResource MyItemsViewSource}">

</DataGrid>

注意: "scm" 命名空间前缀指向 SortDescription 类所在的 System.ComponentModel 命名空间。

xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"

编辑: 我认为足够多的人从这篇文章中获得了帮助,因此这个得到点赞的评论应该被包含在这个答案中:

我不得不使用这个来使它工作:

<DataGrid ItemsSource="{Binding Source={StaticResource MyItemsViewSource}}">

@Drew,谢谢,但是SortMemberPath只是指定数据源中的哪个字段与DataGrid中的哪个列相对应。我需要设置当前排序列(和方向)。例如,此DataGrid当前按名称升序排序。 - devuxer
1
这就是如何解决“单击标题列并排序问题”的方法。我不小心忘记了如何最初对网格进行排序,我现在会将其添加到我的答案中。 - Drew Marsh
5
是的 :) 这非常接近我想要的,谢谢。唯一的问题是排序箭头不会出现在表格按列排序的标题中。我可以忍受这个,但箭头会让用户更清楚地知道排序列是什么。对于任何试图做这个的人,需要引用 WindowsBase 才能使用 System.ComponentModel。一旦你添加了引用,你需要这样做:xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase" - devuxer
12
我必须使用<DataGrid ItemsSource="{Binding Source={StaticResource MyItemsViewSource}}">才能让这个工作。 - Samuel Jack

18

我知道这是一个旧帖子,但除了Drew Marsh的答案之外,针对DanM关于列标题箭头不显示的问题...你需要向DataGridColumn添加SortDirection属性:

<DataGridTextColumn Header="Name" Binding="{Binding Name}" SortDirection="Ascending" />

我曾经发布过一个问题,几天后找到了答案:

在XAML中对DataGrid排序时,ColumnHeader箭头未反映


1
这意味着SortDirection属性必须手动匹配SortDescription中的列 - 是否有任何方法让DataGrid自动检测CollectionViewSource的排序并自动显示指示器? - Dai

5
当您看到“ItemsSource不支持CollectionViewSource”异常时,您可以将DataGrid的DataContext设置为“MyItemsViewSource”,并像这样将ItemsSource设置为{Binding}:
<DataGrid DataContext="{StaticResource MyItemsViewSource}" ItemsSource="{Binding}">
</DataGrid>

2
我今年已经第三次回到这篇文章,因为我总是忘记做这个非常重要的部分/拼图!谢谢你发布它。 - denis morozov

3

当你看到 ItemsSource doesn't support CollectionViewSource 异常时,在将集合引用到数据表之前,可以使用Linq对集合进行排序:

ObservableCollection<MyDataClass> myCollection = new ObservableCollection<MyDataClass>();
dataGrid.ItemsSource = from item in myCollection orderby item select item;

您需要为MyDataClass实现IComparable接口:

public class MyDataClass : IComparable<MyDataClass> {
    public int CompareTo(Classified other) {
        return other.Value.CompareTo(this.Value); // DESC
        return this.Value.CompareTo(other.Value); // ASC
    }
}

这对我很有用,因为我试图使用Lambda来排序BindlingList。这个方法可行,而Lambda不行! - DerpyNerd

0

这对我有效。

ListSortDirection sortDirection;
int selectedColumnIndex;
private void customerDataGrid_Sorting(object sender, DataGridSortingEventArgs e)
{
    selectedColumnIndex = e.Column.DisplayIndex;
    sortDirection = (e.Column.SortDirection == ListSortDirection.Ascending ? ListSortDirection.Descending: ListSortDirection.Ascending);
}

private void applySortDescriptions(ListSortDirection listSortDirection)
{
    //Clear current sort descriptions 
    customerDataGrid.Items.SortDescriptions.Clear();

    //Get property name to apply sort based on desired column 
    string propertyName = customerDataGrid.Columns[selectedColumnIndex].SortMemberPath;

    //Add the new sort description 
    customerDataGrid.Items.SortDescriptions.Add(new SortDescription(propertyName, listSortDirection));

    //apply sort 
    applySortDirection(listSortDirection);

    //refresh items to display sort 
    customerDataGrid.Items.Refresh();
}

private void applySortDirection(ListSortDirection listSortDirection)
{
    customerDataGrid.Columns[selectedColumnIndex].SortDirection = listSortDirection;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接