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

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

问题描述

我有一个WPF DataGrid绑定到一个CollectionViewSource封装了一个ObservableCollection。此CollectionViewSource有两个主要目标:



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



2)按a)主要对组名进行排序(如上所述)和b)单个组项目。通过将自定义IComparer附加到CollectionViewSource的CustomSort属性来实现此目的。



这在很大程度上非常有用,但是只要单击列标题,排序逻辑被覆盖。我不想禁用排序,但是我想知道是否可以为特定列分配自定义排序顺序?



为了使事情更清晰,假设用户点击ColumnA - 目前,我的CustomSorter封装的排序逻辑被覆盖,DataGrid现在按照该属性进行排序。而不是按所选属性进行排序,而是反转CustomSorter的逻辑。

解决方案

我创建了一对的处理这个问题的附加属性。我希望这对于某个人来说非常有用!



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

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

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

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

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(CustomSortBehavior),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作为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(DataGrid的ItemsSource属性必须是类型,ListCollectionView);

// Sanity check
var sorter = GetCustomSorter(e.Column);
if(sorter == null)return;这个胆量是

//
e.Handled = true;

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

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

要使用它,实现一个ICustomComparer(带无参数构造函数)和你的XAML中:

 < UserControl.Resources> 
< converters:MyComparer x:Key =MyComparer/>
<! - 如果需要,添加更多 - >
< /UserControl.Resources>
< DataGrid行为:CustomSortBehaviour.AllowCustomSort =TrueItemsSource ={Binding MyListCollectionView}>
< DataGrid.Columns>
< DataGridTextColumn Header =TestBinding ={Binding MyValue}行为:CustomSortBehaviour.CustomSorter ={StaticResource MyComparer}/>
< /DataGrid.Columns>
< / DataGrid>


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

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

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!

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

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(CustomSortBehavior));

    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(CustomSortBehavior), 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;
    }
}

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天全站免登陆