如何使用C# LINQ按年月分组实现三级层级树视图结构
问题原因
你当前代码无法生成正确树形结构有两个核心问题:
- 循环内每次都会覆盖单个
TreeYear实例的属性,且每次都重新初始化Months列表,最终只会保留最后一条遍历到的报价数据,完全没有做分组聚合。 - 你尝试编写的多层GroupBy语法错误,且分组维度选择不对,分组应该从原始的报价数据集出发,而不是基于未正确构造的TreeYear对象做二次分组。
数据模型调整
你当前定义的TreeMonth仅支持绑定单个QuoteSummary对象,而按照你要的年份-月份-关联业务项三级结构,同一个月份节点下会挂载多条关联业务数据,需要先把单对象属性调整为集合类型,否则无法承载同月下的多条数据:
public class TreeYear { public string NodeYear { get; set; } public DateTime CreatedDateTime { get; set; } public List<TreeMonth> Months { get; set; } = new(); } public class TreeMonth { public int MonthID { get; set; } public string MonthName { get; set; } // 单对象改为集合,存储当月所有关联业务项 public List<QuoteSummary> QuoteSummaries { get; set; } = new(); }
如果你的业务场景不需要对同月份数据做聚合,要求每个月份叶子节点直接对应单条业务项,可保留原有单QuoteSummary属性,参考后面的第二种写法即可。
正确LINQ分组实现
直接从原始报价列表做两层分组即可,不需要用复杂的GroupBy重载,逻辑清晰且易维护:
写法1:月份节点聚合当月所有业务项(匹配三级结构标准逻辑)
var allQuotes = QuoteSummary.ToList(); var treeResult = allQuotes // 第一层分组:按报价年份划分根节点 .GroupBy(quote => quote.CreatedTime.Year) .Select(yearGroup => new TreeYear { NodeYear = yearGroup.Key.ToString(), CreatedDateTime = yearGroup.Min(quote => quote.CreatedTime), Months = yearGroup // 第二层分组:同一年份下按月份划分二级节点 .GroupBy(quote => quote.CreatedTime.Month) .Select(monthGroup => new TreeMonth { MonthID = monthGroup.Key, MonthName = getAbbreviatedName(monthGroup.Key), QuoteSummaries = monthGroup.ToList() }) // 按月份数字升序排列,避免10月、11月排在1月前面 .OrderBy(month => month.MonthID) .ToList() }) // 按年份升序排列根节点 .OrderBy(year => year.NodeYear) .ToList();
写法2:单条业务项对应一个月份叶子节点(无需聚合场景)
如果不需要在月份节点下挂载多条业务项,保留你原来的TreeMonth单QuoteSummary定义即可,用以下写法:
var allQuotes = QuoteSummary.ToList(); var treeResult = allQuotes .GroupBy(quote => quote.CreatedTime.Year) .Select(yearGroup => new TreeYear { NodeYear = yearGroup.Key.ToString(), CreatedDateTime = yearGroup.Min(quote => quote.CreatedTime), Months = yearGroup .Select(quote => new TreeMonth { MonthID = quote.CreatedTime.Month, MonthName = getAbbreviatedName(quote.CreatedTime.Month), QuoteSummary = quote }) .OrderBy(month => month.MonthID) .ToList() }) .OrderBy(year => year.NodeYear) .ToList();
内容的提问来源于stack exchange,提问作者ScuffedCoder
相关产品推荐
相关产品推荐

