【问题标题】:Sort a WPF DataGrid by a value within a group按组中的值对 WPF DataGrid 进行排序
【发布时间】:2017-04-11 06:13:16
【问题描述】:

我有一个由数据库查询填充的 WPF DataGrid。初始结果在 SQL 中进行分组排序:

我希望我的用户能够按任意列排序,但简单地按“值”排序会混淆组。我希望组保持分组,同时按指定列排序。

例如,按“值”列升序排序,应按每个组中的最小“值”对进行排序。结果应该是:

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

【问题讨论】:

    标签: c# wpf linq


    【解决方案1】:

    这是一个小例子,如何根据需要进行分组,你可以更改它,你的列表来自 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;
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      您确实需要通过以下方式实现排序处理程序(参见代码中的 cmets):

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-12-10
        • 2014-12-12
        • 2010-12-24
        • 2011-08-12
        • 2017-06-09
        • 2013-11-24
        • 2017-10-06
        • 1970-01-01
        相关资源
        最近更新 更多