2017-04-11 103 views
1

我有一個WPF DataGrid,它由數據庫查詢填充。初步結果進行分組和分類在SQL:對組中的值對WPF DataGrid排序

Before

我希望我的用戶能夠通過任意列進行排序,然而,僅僅通過「價值」訂貨會混淆的組。我希望這些組保持分組狀態,同時按指定的列進行排序。

例如,按列「值」進行排序,升序應按每組中的最小「值」對組排序。結果應該是:

After

我已經有了一種處理工作,我懷疑LINQ的可能是有用的在這裏,但我似乎無法找到一種方法來排序價值和組名。

回答

0

這是小例子如何分組像你想,你可以改變它,你的列表來自數據庫,你可以做同樣的像我一樣,不要忘記約了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; 
    } 

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