按运行时已知的多个键进行分组

我有一个telerik网格,我将一个对象列表数据绑定到一个页面上。 用户可以在查看数据时根据自己的喜好对列进行分组。 我正在编写一个函数来将此数据导出到Excel文档中,并希望保留用户在页面上的分组。 我能够获取用户分组的对象属性的字符串名称。

我坚持的是如何在运行时进行分组。 有很多这样的例子: 使用lambda分组多列,描述如何在编译时提前知道如何按多个属性进行分组。 但是,我不知道在运行期间要分组的内容。

有关如何在运行时进行分组的建议吗?

我会用Dynamic Linq( http://weblogs.asp.net/scottgu/dynamic-linq-part-1-using-the-linq-dynamic-query-library )做到这一点

例:

using System; using System.Collections.Generic; using System.Linq; using System.Linq.Dynamic; //have to install this via nuget or download it public class Person { public string FirstName { get; set; } public string LastName { get; set; } public DateTime DOB { get; set; } } class Program { static void Main(string[] args) { var peeps = new List{ new Person(){ FirstName="Tim", LastName="Smith", DOB = DateTime.Now}, new Person(){ FirstName="Tim", LastName="Smith", DOB = DateTime.Now.AddDays(1)}, new Person(){ FirstName="Mike", LastName="Smith", DOB = DateTime.Now.AddDays(2)}, new Person(){ FirstName="Frank", LastName="Jones", DOB = DateTime.Now.AddDays(3)}, }; var eq = peeps.GroupBy("new (LastName, FirstName)", "it").Select("new(it.Key as Key, it as People)"); ; foreach (dynamic el in eq) { Console.WriteLine(el.Key); foreach (var person in el.People as IEnumerable) { Console.WriteLine(person.LastName + " " + person.DOB); } } } } 

你可能正在寻找像这个问题的答案,特别是:

 var myData = gridData.AsEnumerable() .GroupBy(r => r, new MyDataComparer(keys)) .ToList(); internal class MyDataComparer : IEqualityComparer { private readonly string[] _keys; public MyDataComparer(string[] keys) { _keys = keys; // keep the keys to compare by. } public bool Equals(MyDataType x, MyDataType y) { // a simple implementation that checks if all the required fields // match. This might need more work. bool areEqual = true; foreach (var key in _keys) { areEqual &= (x[key].Equals(y[key])); } return areEqual; } public int GetHashCode(DataRow obj) { // Add implementation here to create an aggregate hashcode. } } 

您尝试按运行时具有的特定属性的名称进行分组。 除了它固定在2个filter之外,它与此类似。 这只是你的另一个选择。 使用linq pad来测试它。

filter的数量是固定的还是动态的?

 void Main() { var mySchool = new List{ new School{Student = "Student A", Teacher = "Teacher A", Subject = "Math", Grades = 80}, new School{Student = "Student B", Teacher = "Teacher A", Subject = "Math", Grades = 65}, new School{Student = "Student C", Teacher = "Teacher A", Subject = "Math", Grades = 95}, new School{Student = "Student A", Teacher = "Teacher B", Subject = "History", Grades = 80}, new School{Student = "Student B", Teacher = "Teacher B", Subject = "History", Grades = 100}, new School{Student = "Student A", Teacher = "Teacher C", Subject = "English", Grades = 100}, new School{Student = "Student C", Teacher = "Teacher B", Subject = "English", Grades = 100}, new School{Student = "Student D", Teacher = "Teacher B", Subject = "English", Grades = 90}, }; GroupByFilters("Teacher", "Subject", mySchool); GroupByFilters("Subject", "Teacher", mySchool); } public void GroupByFilters(string filter1, string filter2, List school) { PropertyInfo prop1 = typeof(School).GetProperties() .Where(x => x.Name == filter1) .First(); PropertyInfo prop2 = typeof(School).GetProperties() .Where(x => x.Name == filter2) .First(); var grouping = from s in school group s by new {filter1 = prop1.GetValue(s), filter2 = prop2.GetValue(s)} into gr select new { Filter1 = gr.Key.filter1, Filter2 = gr.Key.filter2, TotalGrades = gr.Sum(x => x.Grades), Count = gr.Count(), Average = gr.Average(x => x.Grades) }; grouping.Dump(); // Linq pad specific } // Define other methods and classes here public class School{ public string Student {get;set;} public string Teacher {get;set;} public string Subject {get;set;} public int Grades {get;set;} } 

Filter1 Filter2 TotalGrades Count Average

老师A Math 240 3 80

B老师历史180 2 90

老师C英语100 1 100

B老师英语190 2 95


Filter1 Filter2 TotalGrades Count Average

数学老师A 240 3 80

历史老师B 180 2 90

英语老师C 100 1 100

英语老师B 190 2 95