Pre-sorting a DataGrid in WPF

2019-01-15 05:49发布

问题:

I have a DataGrid in WPF app with several columns, including a Name column. If the users switches to a particular view, I want the data to be pre-sorted by Name (and I'd like a sort arrow to appear in the Name header just as if the user had clicked that header). However, I can't find the expected properties to make this happen. I was looking for something like SortColumn, SortColumnIndex, SortDirection, etc.

Is it possible to specify the default sort column and direction in markup (XAML) or is that not supported by the WPF Toolkit DataGrid?

回答1:

Assuming you're talking about the WPF Toolkit DataGrid control, you need only set the CanUserSortColumns property to true and then set the SortMemberPath property of each DataGridColumn in the DataGrid.

As far as sorting the collection initially, you must use a CollectionViewSource and set the sort on that and then assign that as the ItemsSource of your DataGrid. If you're doing this in XAML then it would be as easy as:

<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>

NOTE: the "scm" namespace prefix maps to System.ComponentModel where the SortDescription class lives.

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

EDIT: I think enough people got help from this post, that this upvoted comment should be included in this answer:

I had to use this to get it to work:

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


回答2:

I know this is an old post but in addition to Drew Marsh's answer and in response to DanM's issue with the column header's arrows not appearing... You need to add the SortDirection property to the DataGridColumn:

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

I posted a question about this and found the answer a few days later:

ColumnHeader arrows not reflected when sorting a DataGrid in XAML



回答3:

When you see ItemsSource doesn't support CollectionViewSource exception then you can set the DataContext of DataGrid as 'MyItemsViewSource' and ItemsSource as {Binding} like this:

<DataGrid DataContext="{StaticResource MyItemsViewSource}" ItemsSource="{Binding}">
</DataGrid>


回答4:

When you see ItemsSource doesn't support CollectionViewSource exception, you can sort collection by Linq before you refer it to a DataGrid:

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

You have to implement IComparable interface to MyDataClass:

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


回答5:

This works for me.

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;
}