按组内的值对WPF DataGrid进行排序

时间:2017-04-11 06:13:17

标签: c# wpf linq

我有一个WPF DataGrid,它由数据库查询填充。初始结果按SQL分组和排序:

Before

我希望我的用户能够按任意列进行排序,但只需通过" Value"会混淆群体。我希望这些组保持分组,同时按指定的列排序。

例如,按列排序"值",升序,应按的最小值排序"值"在每个小组内。结果应该是:

After

我已经有一个排序处理程序工作,我怀疑Linq在这里可能有用,但我似乎无法找到一种方法来对Value和GroupName进行排序。

2 个答案:

答案 0 :(得分:0)

这是一个小例子如何分组你想要的,你可以改变它,你的列表来自db,你可以像我一样做,并且不要忘记IComparable

static void Main(string[] args)
    {
        List<MyClass> inputlist = new List<MyClass>();
        inputlist.Add(new MyClass { GroupName = "A", Value = 10 });
        inputlist.Add(new MyClass { GroupName = "A", Value = 15 });
        inputlist.Add(new MyClass { GroupName = "A", Value = 20 });
        inputlist.Add(new MyClass { GroupName = "B", Value = 1 });
        inputlist.Add(new MyClass { GroupName = "B", Value = 10 });
        inputlist.Add(new MyClass { GroupName = "B", Value = 15 });
        inputlist.Add(new MyClass { GroupName = "C", Value = 5 });
        inputlist.Add(new MyClass { GroupName = "C", Value = 10 });
        inputlist.Add(new MyClass { GroupName = "C", Value = 15 });

        List<MyClass> outputlist = new List<MyClass>();

        foreach (var item in 
                inputlist.GroupBy(x => x.GroupName).Select(x => new MyClass
                {
                    GroupName = x.First().GroupName,
                    Value = x.Min().Value
                }).ToList().OrderBy(x => x.Value))
        {
            outputlist.AddRange(inputlist.Where(x => x.GroupName == item.GroupName));
        }

        foreach (var item in outputlist)
        {
            Console.WriteLine(item.GroupName + " " + item.Value);
        }
        Console.ReadLine();
    }
}

public class MyClass : IComparable
{
    public string GroupName { get; set; }
    public int Value { get; set; }

    public int CompareTo(object value)
    {
        int val = (int)Value;
        if (this.Value > val) return -1;
        if (this.Value == val) return 0;
        return 1;
    }

}

答案 1 :(得分:0)

您需要确实以下列方式实现排序处理程序(请参阅代码中的注释):

private void OnSorting(object sender, DataGridSortingEventArgs e) {
    if (e.Column.SortMemberPath == "Value") {
        // get view
        var source = (ListCollectionView) CollectionViewSource.GetDefaultView(this.Items);
        // manually change sort direction to the next value
        // so null > ascending > descending > back to null
        var sort = e.Column.SortDirection;
        if (sort == null)
            sort = ListSortDirection.Ascending;
        else if (sort == ListSortDirection.Ascending)
            sort = ListSortDirection.Descending;
        else
            sort = null;

        if (sort != null) {
            // first figure out correct group ordering
            var sortedGroups = dataGrid.ItemsSource.OfType<Item>()
                .GroupBy(c => c.GroupName)
                .Select(c => new {GroupName = c.Key, MinValue = c.Min(r => r.Value)})
                .OrderBy(c => c.MinValue)
                .Select(c => c.GroupName)
                .ToArray();
            // now set collection view custom sort to out comparer
            source.CustomSort = new ItemComparer(sortedGroups, sort == ListSortDirection.Ascending);
        }
        else {
            // otherwise remove custom sort and sort as usual
            source.CustomSort = null;
        }
        e.Column.SortDirection = sort;
        e.Handled = true;
    }
}

public class ItemComparer : IComparer {
    private readonly string[] _sortedGroups;
    private readonly bool _asc;

    public ItemComparer(string[] sortedGroups, bool asc) {
        _sortedGroups = sortedGroups;
        _asc = asc;
    }

    public int Compare(object ox, object oy) {
        var x = (Item) ox;
        var y = (Item) oy;

        if (x.GroupName == y.GroupName) {
            // if group names are the same - sort as usual, by Value
            return x.Value.CompareTo(y.Value) * (_asc ? 1 : -1);
        }
        // otherwise - sort by group name using the order we already figured out at previous step
        return (Array.IndexOf(_sortedGroups, x.GroupName) - Array.IndexOf(_sortedGroups, y.GroupName)) * (_asc ? 1 : -1);
    }
}