对 WPF 数据网格中的多列进行排序

Posted

技术标签:

【中文标题】对 WPF 数据网格中的多列进行排序【英文标题】:Sort on multiple columns in WPF datagrid 【发布时间】:2011-09-22 02:17:33 【问题描述】:

如何设置我的 WPF 数据网格以对多个列进行排序,类似于具有两个可排序列,单击第一列的标题进行主要排序,然后 SHIFT 单击第二列的标题进行次要排序.我希望当用户单击第一列的标题时自动进行多列排序,而无需 SHIFT 单击第二列标题。有没有办法完全在 xaml 中做到这一点?如果不是,我怎么能在后面的代码中做到这一点?目前使用的是 VB.Net,但如果你有一个 C# sn-p 是可以接受的。谢谢!

【问题讨论】:

【参考方案1】:

您可以通过像这样添加 System.ComponentModel 命名空间来做到这一点:

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

然后在 CollectionViewSource XAML 中添加新的 SortDescriptions,如下所示:

<CollectionViewSource … >
            <CollectionViewSource.SortDescriptions>
                <scm:SortDescription PropertyName="Column1"/>
                <scm:SortDescription PropertyName="Column2"/>
            </CollectionViewSource.SortDescriptions>
</CollectionViewSource>

这将对column1,column2上的数据网格进行排序。

编辑:

在后面使用 C# 代码也很容易做到这一点:

    private void btnSort_Click(object sender, RoutedEventArgs e)
    
        System.Windows.Data.CollectionViewSource myViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("The_ViewSource_Name")));
        myViewSource.SortDescriptions.Add(new SortDescription("Column1", ListSortDirection.Ascending));
        myViewSource.SortDescriptions.Add(new SortDescription("Column2", ListSortDirection.Ascending));
    

编辑2:

可以采取解决方法来捕获列标题左键单击事件并防止网格在该列上排序,如下所示:

禁用名为的网格属性 CanUserSortColumns

将此代码添加到网格中 PreviewMouseLeftButtonUp 事件:

private void myDataGrid_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)

    DependencyObject dep = (DependencyObject)e.OriginalSource;
    while ((dep != null) &&
    !(dep is DataGridCell) &&
    !(dep is DataGridColumnHeader))
    
        dep = VisualTreeHelper.GetParent(dep);
    

    if (dep == null)
        return;

    if (dep is DataGridColumnHeader)
    
        DataGridColumnHeader columnHeader = dep as DataGridColumnHeader;
        // check if this is the wanted column
        if (columnHeader.Column.Header.ToString() == "The_Wanted_Column_Title")
        
            System.Windows.Data.CollectionViewSource myViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("myViewSource")));
            myViewSource.SortDescriptions.Clear();
            myViewSource.SortDescriptions.Add(new SortDescription("Column1", ListSortDirection.Ascending));
            myViewSource.SortDescriptions.Add(new SortDescription("Column2", ListSortDirection.Ascending));
        
        else
        
            //usort the grid on clicking on any other columns, or maybe do another sort combination
            System.Windows.Data.CollectionViewSource myViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("myViewSource")));
            myViewSource.SortDescriptions.Clear();
        

    

您可以修改和扩展此代码以满足您的要求。

【讨论】:

OP 询问如何允许用户通过单击多个列标题对网格进行排序,而不是如何以编程方式对基础集合进行一次排序。 @djacobson 我想我很好地阅读了这个问题,他写道:“有没有办法完全在 xaml 中做到这一点?” @djacobson 除了单击多个列标题之外,网格会自动按所选列排序。 @djacobson 由于这个解释我认为你的反对票是不公平的。 正确@djacobson。我知道上述用于对基础视图进行排序的方法,但这对标题单击的排序行为没有任何作用。另外,要明确的是,我知道如何根据多次标题单击(单击、SHIFT 单击)进行排序,我想知道的是如何仅单击一次标题就对两列进行排序。【参考方案2】:

我希望这对其他人有所帮助。我的解决方案保留了默认的排序功能,并允许在多列上进行排序。

在你的数据网格上放置一个排序事件

<DataGrid x:Name="dataGridName" Sorting="dataGridName_Sorting">

现在在你的代码后面

private void dataGridName_Sorting(object sender, DataGridSortingEventArgs e)

    var dgSender = (DataGrid) sender;
    var cView = CollectionViewSource.GetDefaultView(dgSender.ItemsSource);

    //Alternate between ascending/descending if the same column is clicked 
    ListSortDirection direction = ListSortDirection.Ascending;
    if (cView.SortDescriptions.FirstOrDefault().PropertyName == e.Column.SortMemberPath)
        direction = cView.SortDescriptions.FirstOrDefault().Direction == ListSortDirection.Descending ? ListSortDirection.Ascending : ListSortDirection.Descending;

    cView.SortDescriptions.Clear();
    AddSortColumn((DataGrid)sender, e.Column.SortMemberPath, direction);
    //To this point the default sort functionality is implemented

    //Now check the wanted columns and add multiple sort 
    if (e.Column.SortMemberPath == "WantedColumn")
    
        AddSortColumn((DataGrid)sender, "SecondColumn", direction);
    
    e.Handled = true;


private void AddSortColumn(DataGrid sender, string sortColumn, ListSortDirection direction)

    var cView = CollectionViewSource.GetDefaultView(sender.ItemsSource);
    cView.SortDescriptions.Add(new SortDescription(sortColumn, direction));
    //Add the sort arrow on the DataGridColumn
    foreach (var col in sender.Columns.Where(x => x.SortMemberPath == sortColumn))
    
        col.SortDirection = direction;
    

DataGridColumn 上的 sortDirection 允许在网格上显示箭头。

【讨论】:

以上是关于对 WPF 数据网格中的多列进行排序的主要内容,如果未能解决你的问题,请参考以下文章

基于单击列标题在WPF中对数据网格进行排序

以编程方式对 wpf 数据网格进行排序

在多列上对剑道网格进行排序

按多列对数据视图中的结果集进行排序

如何从数据网格中获取已排序的项目源

Python对多列文件中的数字进行排序[重复]