每列的 WPF DataGrid CustomSort [英] WPF DataGrid CustomSort for each Column

查看:29
本文介绍了每列的 WPF DataGrid CustomSort的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 WPF DataGrid 绑定到一个 CollectionViewSource,它封装了一个 ObservableCollection.这个 CollectionViewSource 有两个主要目标:

I have a WPF DataGrid bound to a CollectionViewSource that encapsulates an ObservableCollection. This CollectionViewSource has two main objectives:

1) 按 T 的特定属性对每个项目进行分组.我在 GroupDescription 中使用 ValueConverter 来获得我想要的分组行为.

1) To group each item by a specific property of T. I'm using a ValueConverter in the GroupDescription to get the grouping behaviour I want.

2) 按 a) 主要是组名称(如上定义)和 b) 各个组项目对网格进行排序.我通过将自定义 IComparer 附加到 CollectionViewSource 的CustomSort"属性来实现这一点.

2) To sort the grid by a) primarily the group name (as defined above) and b) the individual group items. I'm achieving this by attaching a custom IComparer to the CollectionViewSource's 'CustomSort' property.

这在大多数情况下效果很好,但是一旦单击列标题,排序逻辑就会被覆盖.我不想禁用排序,但是我想知道是否可以为特定列分配自定义排序顺序?

This works great for the most part, however as soon as a column header is clicked, the sorting logic is overridden. I don't want to disable sorting, however I was wondering if it was possible to assign a custom sorting order for a specific column?

为了让事情更清楚一点,假设用户单击了ColumnA"——此时,我的 CustomSorter 封装的排序逻辑被覆盖,DataGrid 现在按该属性排序.我不想按所选属性排序,而是反转 CustomSorter 的逻辑.

To make things a bit clearer, suppose a user clicks 'ColumnA' - at the moment, the sorting logic encapsulated by my CustomSorter is overridden and the DataGrid is now sorted by that property. Rather than sorting by the selected property, I'd like to instead reverse the logic of the CustomSorter.

推荐答案

我创建了几个附加属性来处理这个问题.我希望这对某人有用!

I created a couple of attached properties which handle this issue. I hope this comes in handy for someone!

首先 - 用于定向比较器的简单界面.这扩展了 IComparer,但为我们提供了另一个属性(SortDirection).您的实现应该使用它来确定元素的正确顺序(否则会丢失).

First - a simple interface for your directionalised comparer. This extends IComparer but gives us one more property (SortDirection). Your implementation should use this to determine the correct ordering of elements (which would otherwise have been lost).

public interface ICustomSorter : IComparer
{
    ListSortDirection SortDirection { get; set; }
}

接下来是附加的行为 - 这有两件事:1) 告诉网格使用自定义排序逻辑 (AllowCustomSort=true) 和 b) 使我们能够在每列级别设置此逻辑.

Next is the attached behavior - this does two things: 1) tells the grid to use custom sort logic (AllowCustomSort=true) and b) gives us the ability to set this logic at a per-column level.

public class CustomSortBehaviour
{
    public static readonly DependencyProperty CustomSorterProperty =
        DependencyProperty.RegisterAttached("CustomSorter", typeof(ICustomSorter), typeof(CustomSortBehaviour));

    public static ICustomSorter GetCustomSorter(DataGridColumn gridColumn)
    {
        return (ICustomSorter)gridColumn.GetValue(CustomSorterProperty);
    }

    public static void SetCustomSorter(DataGridColumn gridColumn, ICustomSorter value)
    {
        gridColumn.SetValue(CustomSorterProperty, value);
    }

    public static readonly DependencyProperty AllowCustomSortProperty =
        DependencyProperty.RegisterAttached("AllowCustomSort", typeof(bool),
        typeof(CustomSortBehaviour), new UIPropertyMetadata(false, OnAllowCustomSortChanged));

    public static bool GetAllowCustomSort(DataGrid grid)
    {
        return (bool)grid.GetValue(AllowCustomSortProperty);
    }

    public static void SetAllowCustomSort(DataGrid grid, bool value)
    {
        grid.SetValue(AllowCustomSortProperty, value);
    }

    private static void OnAllowCustomSortChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var existing = d as DataGrid;
        if (existing == null) return;

        var oldAllow = (bool)e.OldValue;
        var newAllow = (bool)e.NewValue;

        if (!oldAllow && newAllow)
        {
            existing.Sorting += HandleCustomSorting;
        }
        else
        {
            existing.Sorting -= HandleCustomSorting;
        }
    }

    private static void HandleCustomSorting(object sender, DataGridSortingEventArgs e)
    {
        var dataGrid = sender as DataGrid;
        if (dataGrid == null || !GetAllowCustomSort(dataGrid)) return;

        var listColView = dataGrid.ItemsSource as ListCollectionView;
        if (listColView == null)
            throw new Exception("The DataGrid's ItemsSource property must be of type, ListCollectionView");

        // Sanity check
        var sorter = GetCustomSorter(e.Column);
        if (sorter == null) return;

        // The guts.
        e.Handled = true;

        var direction = (e.Column.SortDirection != ListSortDirection.Ascending)
                            ? ListSortDirection.Ascending
                            : ListSortDirection.Descending;

        e.Column.SortDirection = sorter.SortDirection = direction;
        listColView.CustomSort = sorter;
    }
}

要使用它,请在您的 XAML 中实现 ICustomComparer(使用无参数构造函数):

To use it, implement an ICustomComparer (with a parameterless constructor) and in your XAML:

<UserControl.Resources>
    <converters:MyComparer x:Key="MyComparer"/>
    <!-- add more if you need them -->
</UserControl.Resources>
<DataGrid behaviours:CustomSortBehaviour.AllowCustomSort="True" ItemsSource="{Binding MyListCollectionView}">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Test" Binding="{Binding MyValue}" behaviours:CustomSortBehaviour.CustomSorter="{StaticResource MyComparer}" />
    </DataGrid.Columns>
</DataGrid>

这篇关于每列的 WPF DataGrid CustomSort的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆