Как установить стандартное направление сортировки по убыванию для столбца WPF DataGrid?

У меня есть WPF DataGrid с сортируемыми столбцами. Я не хочу предварительно сортировать сетку по какому-либо конкретному столбцу. Я просто хочу, чтобы направление сортировки по умолчанию, когда пользователь впервые щелкает заголовок столбца, было убывающим, а не восходящим.

Ни SortDescription.Direction для CollectionViewSource, ни свойство SortDirection объекта DataGridTextColumns не влияют на направление сортировки по умолчанию при изменении столбца сортировки. Он всегда выбирает возрастание по первому щелчку заголовка столбца.

В 99% случаев это должно происходить по убыванию, и переключение столбцов в рабочем процессе пользователя происходит часто, так что это добавляет много ненужных кликов. Я бы очень предпочел решение XAML, если оно есть, но при необходимости прибегну к хитрости кода.

1 ответ

Решение

Кажется, вы не можете сделать это без небольшого вмешательства в обработчики сортировки, потому что сортировка по умолчанию, выполняемая DataGrid, начинается следующим образом:

ListSortDirection direction = ListSortDirection.Ascending;
ListSortDirection? sortDirection = column.SortDirection;
if (sortDirection.HasValue && sortDirection.Value == ListSortDirection.Ascending)
    direction = ListSortDirection.Descending;

Таким образом, только если столбец был отсортирован ранее, и этот тип сортировки был Ascending - он перевернет его на Descending. Однако с крошечной взломать вы можете достичь того, что вы хотите. Сначала подпишитесь на событие DataGrid.Sorting, и там:

private void OnSorting(object sender, DataGridSortingEventArgs e) {
    if (e.Column.SortDirection == null)
         e.Column.SortDirection = ListSortDirection.Ascending;
    e.Handled = false;
}

Так что в принципе, если еще не было сортировки - вы переключаете его на Ascending и передать его на сортировку по умолчанию DataGrid (установив e.Handled в false). В начале сортировки это перевернет это к Descending для вас то, что вы хотите.

Вы можете сделать это в xaml с помощью прикрепленного свойства, например:

public static class DataGridExtensions {        
    public static readonly DependencyProperty SortDescProperty = DependencyProperty.RegisterAttached(
        "SortDesc", typeof (bool), typeof (DataGridExtensions), new PropertyMetadata(false, OnSortDescChanged));

    private static void OnSortDescChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
        var grid = d as DataGrid;
        if (grid != null) {
            grid.Sorting += (source, args) => {
                if (args.Column.SortDirection == null) {
                    // here we check an attached property value of target column
                    var sortDesc = (bool) args.Column.GetValue(DataGridExtensions.SortDescProperty);
                    if (sortDesc) {
                        args.Column.SortDirection = ListSortDirection.Ascending;
                    }
                }
            };
        }
    }

    public static void SetSortDesc(DependencyObject element, bool value) {
        element.SetValue(SortDescProperty, value);
    }

    public static bool GetSortDesc(DependencyObject element) {
        return (bool) element.GetValue(SortDescProperty);
    }
}

Тогда в вашем xaml:

<DataGrid x:Name="dg" AutoGenerateColumns="False" ItemsSource="{Binding Items}" local:DataGridExtensions.SortDesc="True">
    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding Value}"
                            Header="Value"
                            local:DataGridExtensions.SortDesc="True" />
    </DataGrid.Columns>
</DataGrid>

Так что в основном вы отмечаете DataGrid сам с SortDesc=true, чтобы подписаться на событие сортировки, а затем вы отмечаете только те столбцы, которые нужно отсортировать desc. Вы также можете связать SortDesc к вашей модели, если логика для определения этого есть.

Другие вопросы по тегам